From 86f31acf6789be116dcc54ed85b069a37c0f7aa8 Mon Sep 17 00:00:00 2001 From: Mel Date: Thu, 11 Aug 2022 01:25:47 +0000 Subject: Actual modules and core --- pkg/lang/modules/core/natives.go | 166 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 pkg/lang/modules/core/natives.go (limited to 'pkg/lang/modules/core/natives.go') diff --git a/pkg/lang/modules/core/natives.go b/pkg/lang/modules/core/natives.go new file mode 100644 index 0000000..3035b80 --- /dev/null +++ b/pkg/lang/modules/core/natives.go @@ -0,0 +1,166 @@ +package core + +import ( + "fmt" + "jinx/pkg/lang/vm/code" + "jinx/pkg/lang/vm/executor" + "jinx/pkg/lang/vm/value" +) + +var Natives = []any{ + n(":core:setup_type", 1, func(exe executor.Exectutor, args []value.Value) (value.Value, error) { + // Add the very important "$add_method" method to the Type type. + // Without it no other methods can be created. + typeRef, err := ensureType[value.TypeRefData](args[0], value.TypeRefType) + if err != nil { + return value.Value{}, err + } + + addMethodGlobal, ok, err := exe.GetGlobal(":core:Type:$add_method#native") + if err != nil { + return value.Value{}, err + } + + if !ok { + panic("missing Type:$add_method implementation") + } + + addMethodFn, err := ensureType[value.FunctionData](addMethodGlobal, value.FunctionType) + if err != nil { + return value.Value{}, err + } + + typeRef.AddMethod( + exe.Mem(), + "$add_method", + value.NewNativeFunction(addMethodFn.Native(), 2).Data().(value.FunctionData), + ) + + return value.Value{}, nil + }), + n(":core:Type:$add_method", 2, func(exe executor.Exectutor, args []value.Value) (value.Value, error) { + ref, err := ensureTypeThis[value.TypeRefData](exe, value.TypeRefType) + if err != nil { + return value.Value{}, err + } + + fn, err := ensureType[value.FunctionData](args[0], value.FunctionType) + if err != nil { + return value.Value{}, err + } + + nameData, err := ensureType[value.StringData](args[1], value.StringType) + if err != nil { + return value.Value{}, err + } + name, err := nameData.RawString(exe.Mem()) + if err != nil { + return value.Value{}, err + } + + return value.Value{}, ref.AddMethod(exe.Mem(), name, fn) + }), + + n(":core:Int:$init", 0, func(exe executor.Exectutor, args []value.Value) (value.Value, error) { + return value.NewInt(0), nil + }), + n(":core:Float:$init", 0, func(exe executor.Exectutor, args []value.Value) (value.Value, error) { + return value.NewFloat(0.0), nil + }), + n(":core:String:$init", 0, func(exe executor.Exectutor, args []value.Value) (value.Value, error) { + return value.NewString(exe.Mem(), "") + }), + n(":core:Bool:$init", 0, func(exe executor.Exectutor, args []value.Value) (value.Value, error) { + return value.NewBool(false), nil + }), + n(":core:Array:$init", 0, func(exe executor.Exectutor, args []value.Value) (value.Value, error) { + return value.NewArray(exe.Mem(), args) + }), + n(":core:Function:$init", 0, func(exe executor.Exectutor, args []value.Value) (value.Value, error) { + return value.NewFunction(code.NewPos(0, 0), 0), nil + }), + n(":core:Type:$init", 0, func(exe executor.Exectutor, args []value.Value) (value.Value, error) { + return value.NewType(exe.Mem(), "") + }), + + n(":core:Array:push", 2, func(exe executor.Exectutor, args []value.Value) (value.Value, error) { + array, err := ensureType[value.ArrayData](args[0], value.ArrayType) + if err != nil { + return value.Value{}, err + } + + element := args[1] + return value.Value{}, array.Push(exe.Mem(), element) + }), + n(":core:Array:pop", 1, func(exe executor.Exectutor, args []value.Value) (value.Value, error) { + array, err := ensureType[value.ArrayData](args[0], value.ArrayType) + if err != nil { + return value.Value{}, err + } + + return array.Pop(exe.Mem()) + }), + n(":core:Array:length", 1, func(exe executor.Exectutor, args []value.Value) (value.Value, error) { + array, err := ensureType[value.ArrayData](args[0], value.ArrayType) + if err != nil { + return value.Value{}, err + } + + length, err := array.Len(exe.Mem()) + if err != nil { + return value.Value{}, err + } + + return value.NewInt(int64(length)), nil + }), + + n(":core:say", 1, func(exe executor.Exectutor, args []value.Value) (value.Value, error) { + message := args[0] + s, err := message.Data().String(exe.Mem()) + if err != nil { + return value.Value{}, err + } + + fmt.Println(s) + return value.Value{}, nil + }), +} + +type native struct { + name string + argCount int + fn executor.NativeFunc +} + +func n(name string, argCount int, fn executor.NativeFunc) native { + return native{name, argCount, fn} +} + +func (n native) Name() string { + return n.name +} + +func (n native) ArgCount() int { + return n.argCount +} + +func (n native) Fn() executor.NativeFunc { + return n.fn +} + +func ensureTypeThis[D value.Data](exe executor.Exectutor, t value.TypeKind) (D, error) { + this, err := exe.GetThis() + if err != nil { + return *new(D), err + } + + return ensureType[D](this, t) +} + +func ensureType[D value.Data](val value.Value, t value.TypeKind) (D, error) { + if val.Type() != t { + return *new(D), fmt.Errorf("expected type %s, got %s", t, val.Type()) + } + + return val.Data().(D), nil +} -- cgit 1.4.1