Add IHashable and the implementation for all the IExpr types
This commit is contained in:
parent
1d66c2a56e
commit
5ee7e93647
|
@ -4,6 +4,7 @@ go 1.15
|
|||
|
||||
require (
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e
|
||||
github.com/rjeczalik/pkgconfig v0.0.0-20190903131546-94d388dab445
|
||||
github.com/spf13/cobra v1.1.1
|
||||
github.com/spf13/viper v1.7.1
|
||||
)
|
||||
|
|
|
@ -143,6 +143,8 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
|
|||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/rjeczalik/pkgconfig v0.0.0-20190903131546-94d388dab445 h1:HTpnmNOc0MiWqyJqaiKRO3paZOCo+JqGaDN9ZMKy57w=
|
||||
github.com/rjeczalik/pkgconfig v0.0.0-20190903131546-94d388dab445/go.mod h1:TmjBR6hcDoH9/baYY27h9m2Qk2obtYgLAwgGGvsuwPA=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"serene-lang.org/bootstrap/pkg/ast"
|
||||
"serene-lang.org/bootstrap/pkg/hash"
|
||||
)
|
||||
|
||||
// Block struct represents a group of forms. Don't confuse it with
|
||||
|
@ -56,6 +57,11 @@ func (b *Block) GetLocation() ast.Location {
|
|||
return ast.MakeUnknownLocation()
|
||||
}
|
||||
|
||||
func (l *Block) Hash() uint32 {
|
||||
bytes := []byte("TODO")
|
||||
return hash.HashOf(append([]byte{byte(ast.Block)}, bytes...))
|
||||
}
|
||||
|
||||
func (b *Block) ToSlice() []IExpr {
|
||||
return b.body
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import (
|
|||
var BUILTINS = map[string]NativeFunction{
|
||||
"print": MakeNativeFn("print", PrintNativeFn),
|
||||
"require": MakeNativeFn("print", RequireNativeFn),
|
||||
"hash": MakeNativeFn("hash", HashNativeFn),
|
||||
}
|
||||
|
||||
func PrintNativeFn(rt *Runtime, scope IScope, n Node, args *List) (IExpr, IError) {
|
||||
|
@ -44,9 +45,9 @@ func PrintNativeFn(rt *Runtime, scope IScope, n Node, args *List) (IExpr, IError
|
|||
func RequireNativeFn(rt *Runtime, scope IScope, n Node, args *List) (IExpr, IError) {
|
||||
switch args.Count() {
|
||||
case 0:
|
||||
return nil, MakeErrorFor(rt, args, "'require' special form is missing")
|
||||
return nil, MakeErrorFor(rt, args, "'require' function is missing")
|
||||
case 1:
|
||||
return nil, MakeErrorFor(rt, args.First(), "'require' special form needs at least one argument")
|
||||
return nil, MakeErrorFor(rt, args.First(), "'require' function needs at least one argument")
|
||||
default:
|
||||
}
|
||||
|
||||
|
@ -62,3 +63,19 @@ func RequireNativeFn(rt *Runtime, scope IScope, n Node, args *List) (IExpr, IErr
|
|||
return result, nil
|
||||
|
||||
}
|
||||
|
||||
func HashNativeFn(rt *Runtime, scope IScope, n Node, args *List) (IExpr, IError) {
|
||||
if args.Count() != 2 {
|
||||
return nil, MakeErrorFor(rt, args.First(), "'hash' function needs exactly one argument")
|
||||
}
|
||||
|
||||
expr := args.Rest().First()
|
||||
result, err := MakeInteger(expr.Hash())
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result.Node = n
|
||||
return result, nil
|
||||
}
|
||||
|
|
|
@ -18,7 +18,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
package core
|
||||
|
||||
import "serene-lang.org/bootstrap/pkg/ast"
|
||||
import (
|
||||
"serene-lang.org/bootstrap/pkg/ast"
|
||||
"serene-lang.org/bootstrap/pkg/hash"
|
||||
)
|
||||
|
||||
type FalseType struct{}
|
||||
|
||||
|
@ -40,3 +43,8 @@ func (n FalseType) String() string {
|
|||
func (n FalseType) ToDebugStr() string {
|
||||
return "false"
|
||||
}
|
||||
|
||||
func (n FalseType) Hash() uint32 {
|
||||
bytes := []byte("false")
|
||||
return hash.HashOf(append([]byte{byte(ast.False)}, bytes...))
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ import (
|
|||
"fmt"
|
||||
|
||||
"serene-lang.org/bootstrap/pkg/ast"
|
||||
"serene-lang.org/bootstrap/pkg/hash"
|
||||
)
|
||||
|
||||
type nativeFnHandler = func(rt *Runtime, scope IScope, n Node, args *List) (IExpr, IError)
|
||||
|
@ -86,6 +87,11 @@ func (f *Function) GetType() ast.NodeType {
|
|||
return ast.Fn
|
||||
}
|
||||
|
||||
func (f *Function) Hash() uint32 {
|
||||
// TODO: Fix this function to return an appropriate hash for a function
|
||||
return hash.HashOf([]byte(f.String()))
|
||||
}
|
||||
|
||||
func (f *Function) IsMacro() bool {
|
||||
return f.isMacro
|
||||
}
|
||||
|
@ -169,7 +175,12 @@ func (f *NativeFunction) GetType() ast.NodeType {
|
|||
}
|
||||
|
||||
func (f *NativeFunction) String() string {
|
||||
return fmt.Sprintf("<NativeFn: %s>", f.name)
|
||||
return fmt.Sprintf("<NativeFn: %s at %p>", f.name, f)
|
||||
}
|
||||
|
||||
func (f *NativeFunction) Hash() uint32 {
|
||||
// TODO: Fix this function to return an appropriate hash for a function
|
||||
return hash.HashOf([]byte(f.String()))
|
||||
}
|
||||
|
||||
func (f *NativeFunction) ToDebugStr() string {
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"serene-lang.org/bootstrap/pkg/ast"
|
||||
"serene-lang.org/bootstrap/pkg/hash"
|
||||
)
|
||||
|
||||
/** WARNING:
|
||||
|
@ -73,6 +74,11 @@ func (l *List) Rest() ISeq {
|
|||
return MakeList(l.exprs[1:])
|
||||
}
|
||||
|
||||
func (l *List) Hash() uint32 {
|
||||
bytes := []byte("TODO")
|
||||
return hash.HashOf(append([]byte{byte(ast.List)}, bytes...))
|
||||
}
|
||||
|
||||
// END: ISeq ---
|
||||
|
||||
// Implementing ICountable for List ---
|
||||
|
|
|
@ -22,6 +22,7 @@ import (
|
|||
"fmt"
|
||||
|
||||
"serene-lang.org/bootstrap/pkg/ast"
|
||||
"serene-lang.org/bootstrap/pkg/hash"
|
||||
)
|
||||
|
||||
type INamespace interface {
|
||||
|
@ -101,6 +102,10 @@ func (n *Namespace) GetName() string {
|
|||
return n.name
|
||||
}
|
||||
|
||||
func (n *Namespace) Hash() uint32 {
|
||||
return hash.HashOf([]byte(n.String()))
|
||||
}
|
||||
|
||||
func (n *Namespace) hasExternal(nsName string) bool {
|
||||
_, ok := n.externals[nsName]
|
||||
return ok
|
||||
|
|
|
@ -40,3 +40,7 @@ func (n NilType) String() string {
|
|||
func (n NilType) ToDebugStr() string {
|
||||
return "nil"
|
||||
}
|
||||
|
||||
func (n NilType) Hash() uint32 {
|
||||
return 0
|
||||
}
|
||||
|
|
|
@ -18,7 +18,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
package core
|
||||
|
||||
import "serene-lang.org/bootstrap/pkg/ast"
|
||||
import (
|
||||
"serene-lang.org/bootstrap/pkg/ast"
|
||||
"serene-lang.org/bootstrap/pkg/hash"
|
||||
)
|
||||
|
||||
type NothingType struct{}
|
||||
|
||||
|
@ -28,6 +31,11 @@ func (n NothingType) GetType() ast.NodeType {
|
|||
return ast.Nothing
|
||||
}
|
||||
|
||||
func (n NothingType) Hash() uint32 {
|
||||
bytes := []byte("Nothing")
|
||||
return hash.HashOf(append([]byte{byte(ast.Block)}, bytes...))
|
||||
}
|
||||
|
||||
func (n NothingType) GetLocation() ast.Location {
|
||||
return ast.MakeUnknownLocation()
|
||||
}
|
||||
|
|
|
@ -19,10 +19,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
package core
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
|
||||
"serene-lang.org/bootstrap/pkg/ast"
|
||||
"serene-lang.org/bootstrap/pkg/hash"
|
||||
)
|
||||
|
||||
type INumber interface {
|
||||
|
@ -57,14 +60,16 @@ type Integer struct {
|
|||
value int64
|
||||
}
|
||||
|
||||
func (i Integer) Eval() IExpr {
|
||||
return &i
|
||||
}
|
||||
|
||||
func (i Integer) GetType() ast.NodeType {
|
||||
return ast.Number
|
||||
}
|
||||
|
||||
func (i Integer) Hash() uint32 {
|
||||
b := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(b, uint64(i.value))
|
||||
return hash.HashOf(b)
|
||||
}
|
||||
|
||||
func (i Integer) String() string {
|
||||
return fmt.Sprintf("%d", i.value)
|
||||
}
|
||||
|
@ -81,19 +86,38 @@ func (i Integer) F64() float64 {
|
|||
return float64(i.value)
|
||||
}
|
||||
|
||||
func MakeInteger(x interface{}) (*Integer, IError) {
|
||||
var value int64
|
||||
switch x.(type) {
|
||||
case uint32:
|
||||
value = int64(x.(uint32))
|
||||
case int32:
|
||||
value = int64(x.(int32))
|
||||
default:
|
||||
return nil, MakePlainError(fmt.Sprintf("don't know how to make 'integer' out of '%s'", x))
|
||||
}
|
||||
|
||||
return &Integer{
|
||||
value: value,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type Double struct {
|
||||
Node
|
||||
value float64
|
||||
}
|
||||
|
||||
func (d Double) Eval() IExpr {
|
||||
return &d
|
||||
}
|
||||
|
||||
func (d Double) GetType() ast.NodeType {
|
||||
return ast.Number
|
||||
}
|
||||
|
||||
func (d Double) Hash() uint32 {
|
||||
b := make([]byte, 8)
|
||||
|
||||
binary.BigEndian.PutUint64(b, math.Float64bits(d.value))
|
||||
return hash.HashOf(b)
|
||||
}
|
||||
|
||||
func (d Double) String() string {
|
||||
return fmt.Sprintf("%f", d.value)
|
||||
}
|
||||
|
@ -136,3 +160,21 @@ func MakeNumberFromStr(strValue string, isDouble bool) (INumber, error) {
|
|||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func MakeDouble(x interface{}) (*Double, IError) {
|
||||
var value float64
|
||||
switch x.(type) {
|
||||
case uint32:
|
||||
value = float64(x.(uint32))
|
||||
case int32:
|
||||
value = float64(x.(int32))
|
||||
case float32:
|
||||
value = float64(x.(float32))
|
||||
default:
|
||||
return nil, MakePlainError(fmt.Sprintf("don't know how to make 'double' out of '%s'", x))
|
||||
}
|
||||
|
||||
return &Double{
|
||||
value: value,
|
||||
}, nil
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@ import (
|
|||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"serene-lang.org/bootstrap/pkg/dl"
|
||||
)
|
||||
|
||||
/** TODO:
|
||||
|
@ -196,6 +198,10 @@ func (r *Runtime) LookupBuiltin(k string) IExpr {
|
|||
// runtime initialization such as adding default namespaces and vice
|
||||
// versa has to happen here.
|
||||
func MakeRuntime(paths []string, debug bool) *Runtime {
|
||||
_, e := dl.Open("/home/lxsameer/src/serene/serene/bootstrap/examples/ffi/foo/libfoo.so")
|
||||
if e != nil {
|
||||
panic(e)
|
||||
}
|
||||
rt := Runtime{
|
||||
namespaces: map[string]Namespace{},
|
||||
currentNS: "",
|
||||
|
|
|
@ -22,6 +22,7 @@ import (
|
|||
"fmt"
|
||||
|
||||
"serene-lang.org/bootstrap/pkg/ast"
|
||||
"serene-lang.org/bootstrap/pkg/hash"
|
||||
)
|
||||
|
||||
type String struct {
|
||||
|
@ -41,6 +42,11 @@ func (s *String) ToDebugStr() string {
|
|||
return fmt.Sprintf("<%s at %p>", s.content, s)
|
||||
}
|
||||
|
||||
func (s *String) Hash() uint32 {
|
||||
bytes := []byte(s.content)
|
||||
return hash.HashOf(append([]byte{byte(ast.String)}, bytes...))
|
||||
}
|
||||
|
||||
func MakeString(n Node, s string) *String {
|
||||
return &String{n, s}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"serene-lang.org/bootstrap/pkg/ast"
|
||||
"serene-lang.org/bootstrap/pkg/hash"
|
||||
)
|
||||
|
||||
type Symbol struct {
|
||||
|
@ -55,6 +56,11 @@ func (s *Symbol) ToDebugStr() string {
|
|||
return s.String()
|
||||
}
|
||||
|
||||
func (s *Symbol) Hash() uint32 {
|
||||
// TODO: Return a combined hash of nsPart and name
|
||||
return hash.HashOf([]byte(s.nsPart + "/" + s.name))
|
||||
}
|
||||
|
||||
func (s *Symbol) IsRestable() bool {
|
||||
// Weird name ? I know :D
|
||||
return strings.HasPrefix(s.name, "&")
|
||||
|
|
|
@ -18,7 +18,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
package core
|
||||
|
||||
import "serene-lang.org/bootstrap/pkg/ast"
|
||||
import (
|
||||
"serene-lang.org/bootstrap/pkg/ast"
|
||||
"serene-lang.org/bootstrap/pkg/hash"
|
||||
)
|
||||
|
||||
type TrueType struct{}
|
||||
|
||||
|
@ -40,3 +43,8 @@ func (n TrueType) String() string {
|
|||
func (n TrueType) ToDebugStr() string {
|
||||
return "true"
|
||||
}
|
||||
|
||||
func (n TrueType) Hash() uint32 {
|
||||
bytes := []byte("true")
|
||||
return hash.HashOf(append([]byte{byte(ast.True)}, bytes...))
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import (
|
|||
"fmt"
|
||||
|
||||
"serene-lang.org/bootstrap/pkg/ast"
|
||||
"serene-lang.org/bootstrap/pkg/hash"
|
||||
)
|
||||
|
||||
// IPrintable is the interface which any value that wants to have a string
|
||||
|
@ -43,6 +44,7 @@ type IDebuggable interface {
|
|||
type IExpr interface {
|
||||
ast.ILocatable
|
||||
ast.ITypable
|
||||
hash.IHashable
|
||||
IPrintable
|
||||
IDebuggable
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
Serene --- Yet an other Lisp
|
||||
|
||||
Copyright (c) 2020 Sameer Rahmani <lxsameer@gnu.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Package hash provides the hashing functionality
|
||||
package hash
|
||||
|
||||
import "hash/crc32"
|
||||
|
||||
var hashTable *crc32.Table = crc32.MakeTable(crc32.Castagnoli)
|
||||
|
||||
//IHashable is the interface types which allows expressions to have a hash
|
||||
// value that doesn't change through out their life time. The origin
|
||||
// of each expression can be checked by comparing their hashes. Basically
|
||||
// two expressions with the same hash consider to be the same.
|
||||
type IHashable interface {
|
||||
// Returns a 32 bit hash of the the entity which implements it.
|
||||
// The hash should be constant to the life time of the implementor.
|
||||
Hash() uint32
|
||||
}
|
||||
|
||||
func HashOf(in []byte) uint32 {
|
||||
return crc32.Checksum(in, hashTable)
|
||||
}
|
Loading…
Reference in New Issue