aboutsummaryrefslogtreecommitdiff
path: root/pkg/lang/modules
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/lang/modules')
-rw-r--r--pkg/lang/modules/core/compiled.go22
-rw-r--r--pkg/lang/modules/core/core.lang78
-rw-r--r--pkg/lang/modules/core/natives.go166
-rw-r--r--pkg/lang/modules/module.go104
-rw-r--r--pkg/lang/modules/natives/natives.go39
5 files changed, 409 insertions, 0 deletions
diff --git a/pkg/lang/modules/core/compiled.go b/pkg/lang/modules/core/compiled.go
new file mode 100644
index 0000000..ae34cf4
--- /dev/null
+++ b/pkg/lang/modules/core/compiled.go
@@ -0,0 +1,22 @@
+package core
+
+import (
+ "jinx/pkg/lang/modules"
+ "jinx/pkg/lang/vm/code"
+)
+
+var moduleCompiled = []byte{
+ 0xb, 0x54, 0x79, 0x70, 0x65, 0x0, 0xe, 0x3a, 0x63, 0x6f, 0x72, 0x65, 0x3a, 0x73, 0x65, 0x74, 0x75, 0x70, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x23, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0x54, 0x79, 0x70, 0x65, 0x0, 0xb, 0x4e, 0x75, 0x6c, 0x6c, 0x0, 0x10, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x12, 0x24, 0x61, 0x64, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x0, 0x4, 0x24, 0x69, 0x6e, 0x69, 0x74, 0x0, 0x9, 0x5a, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0x49, 0x6e, 0x74, 0x0, 0x10, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x12, 0x24, 0x61, 0x64, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x0, 0x4, 0x24, 0x69, 0x6e, 0x69, 0x74, 0x0, 0x9, 0x9a, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x0, 0x10, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x12, 0x24, 0x61, 0x64, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x0, 0x4, 0x24, 0x69, 0x6e, 0x69, 0x74, 0x0, 0x9, 0xd9, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x0, 0x10, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x12, 0x24, 0x61, 0x64, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x0, 0x4, 0x24, 0x69, 0x6e, 0x69, 0x74, 0x0, 0x9, 0x1a, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0x42, 0x6f, 0x6f, 0x6c, 0x0, 0x10, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x12, 0x24, 0x61, 0x64, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x0, 0x4, 0x24, 0x69, 0x6e, 0x69, 0x74, 0x0, 0x9, 0x5c, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0x41, 0x72, 0x72, 0x61, 0x79, 0x0, 0x10, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x12, 0x24, 0x61, 0x64, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x0, 0x4, 0x24, 0x69, 0x6e, 0x69, 0x74, 0x0, 0x9, 0x9c, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x12, 0x24, 0x61, 0x64, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x0, 0x4, 0x70, 0x75, 0x73, 0x68, 0x0, 0x9, 0xdd, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x12, 0x24, 0x61, 0x64, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x0, 0x4, 0x70, 0x6f, 0x70, 0x0, 0x9, 0x1c, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x12, 0x24, 0x61, 0x64, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x0, 0x4, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x0, 0x9, 0x47, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x0, 0x10, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x12, 0x24, 0x61, 0x64, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x0, 0x4, 0x24, 0x69, 0x6e, 0x69, 0x74, 0x0, 0x9, 0x75, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9, 0xb9, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9, 0xe8, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0x4e, 0x75, 0x6c, 0x6c, 0x0, 0x10, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0x49, 0x6e, 0x74, 0x0, 0x10, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x0, 0x10, 0x4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x0, 0x10, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0x42, 0x6f, 0x6f, 0x6c, 0x0, 0x10, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0x41, 0x72, 0x72, 0x61, 0x79, 0x0, 0x10, 0x7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x0, 0x10, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0x73, 0x61, 0x79, 0x0, 0x10, 0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0x70, 0x69, 0x6e, 0x67, 0x0, 0x1, 0xa, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x17, 0xe, 0x3a, 0x63, 0x6f, 0x72, 0x65, 0x3a, 0x4e, 0x75, 0x6c, 0x6c, 0x3a, 0x24, 0x69, 0x6e, 0x69, 0x74, 0x23, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x0, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x28, 0xa, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x17, 0xe, 0x3a, 0x63, 0x6f, 0x72, 0x65, 0x3a, 0x49, 0x6e, 0x74, 0x3a, 0x24, 0x69, 0x6e, 0x69, 0x74, 0x23, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x0, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x28, 0xa, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x17, 0xe, 0x3a, 0x63, 0x6f, 0x72, 0x65, 0x3a, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x3a, 0x24, 0x69, 0x6e, 0x69, 0x74, 0x23, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x0, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x28, 0xa, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x17, 0xe, 0x3a, 0x63, 0x6f, 0x72, 0x65, 0x3a, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x3a, 0x24, 0x69, 0x6e, 0x69, 0x74, 0x23, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x0, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x28, 0xa, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x17, 0xe, 0x3a, 0x63, 0x6f, 0x72, 0x65, 0x3a, 0x42, 0x6f, 0x6f, 0x6c, 0x3a, 0x24, 0x69, 0x6e, 0x69, 0x74, 0x23, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x0, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x28, 0xa, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x17, 0xe, 0x3a, 0x63, 0x6f, 0x72, 0x65, 0x3a, 0x41, 0x72, 0x72, 0x61, 0x79, 0x3a, 0x24, 0x69, 0x6e, 0x69, 0x74, 0x23, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x0, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x28, 0xe, 0x3a, 0x63, 0x6f, 0x72, 0x65, 0x3a, 0x41, 0x72, 0x72, 0x61, 0x79, 0x3a, 0x70, 0x75, 0x73, 0x68, 0x23, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x0, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0x28, 0xe, 0x3a, 0x63, 0x6f, 0x72, 0x65, 0x3a, 0x41, 0x72, 0x72, 0x61, 0x79, 0x3a, 0x70, 0x6f, 0x70, 0x23, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x0, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x28, 0xe, 0x3a, 0x63, 0x6f, 0x72, 0x65, 0x3a, 0x41, 0x72, 0x72, 0x61, 0x79, 0x3a, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x23, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x0, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x28, 0xa, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x17, 0xe, 0x3a, 0x63, 0x6f, 0x72, 0x65, 0x3a, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x24, 0x69, 0x6e, 0x69, 0x74, 0x23, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x0, 0x24, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x28, 0xe, 0x3a, 0x63, 0x6f, 0x72, 0x65, 0x3a, 0x73, 0x61, 0x79, 0x23, 0x6e, 0x61, 0x74, 0x69, 0x76, 0x65, 0x0, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x24, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0x28, 0x4, 0x50, 0x6f, 0x6e, 0x67, 0x21, 0x0, 0x28,
+}
+
+var moduleCode = code.New(code.Raw(moduleCompiled), code.NewDebugInfo("core"))
+
+var Module = modules.NewModule(
+ "",
+ "core",
+ &moduleCode,
+ []modules.ModuleRef{},
+ []string{
+ "Type", "Null", "Int", "Float", "String", "Bool", "Array", "Function", "say", "ping",
+ },
+)
diff --git a/pkg/lang/modules/core/core.lang b/pkg/lang/modules/core/core.lang
new file mode 100644
index 0000000..e6be2d5
--- /dev/null
+++ b/pkg/lang/modules/core/core.lang
@@ -0,0 +1,78 @@
+type Type {
+}
+
+native(":core:setup_type", Type)
+global Type
+
+type Null {
+ () {
+ native(":core:Null:$init")
+ }
+}
+
+type Int {
+ () {
+ native(":core:Int:$init")
+ }
+}
+
+type Float {
+ () {
+ native(":core:Float:$init")
+ }
+}
+
+type String {
+ () {
+ native(":core:String:$init")
+ }
+}
+
+type Bool {
+ () {
+ native(":core:Bool:$init")
+ }
+}
+
+type Array {
+ () {
+ native(":core:Array:$init")
+ }
+
+ fn push(this, element) {
+ native(":core:Array:push", this, element)
+ }
+
+ fn pop(this) {
+ return native(":core:Array:pop", this)
+ }
+
+ fn length(this) {
+ return native(":core:Array:length", this)
+ }
+}
+
+type Function {
+ () {
+ native(":core:Function:$init")
+ }
+}
+
+fn say(message) {
+ native(":core:say", message)
+}
+
+fn ping() {
+ return "Pong!"
+}
+
+global Null
+global Int
+global Float
+global String
+global Bool
+global Array
+global Function
+
+global say
+global ping \ No newline at end of file
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
+}
diff --git a/pkg/lang/modules/module.go b/pkg/lang/modules/module.go
new file mode 100644
index 0000000..08b9987
--- /dev/null
+++ b/pkg/lang/modules/module.go
@@ -0,0 +1,104 @@
+package modules
+
+import (
+ "fmt"
+ "jinx/pkg/lang/vm/code"
+)
+
+type Module struct {
+ author string
+ name string
+ code *code.Code
+ deps []ModuleRef
+ globals []string
+}
+
+func NewModule(author, name string, code *code.Code, deps []ModuleRef, globals []string) Module {
+ return Module{
+ author: author,
+ name: name,
+ code: code,
+ deps: deps,
+ globals: globals,
+ }
+}
+
+func NewUnknownModule(code *code.Code) Module {
+ return Module{
+ author: "noone",
+ name: "program",
+ code: code,
+ deps: []ModuleRef{
+ CoreModuleRef,
+ },
+ globals: []string{},
+ }
+}
+
+func (m Module) Author() string {
+ return m.author
+}
+
+func (m Module) Name() string {
+ return m.name
+}
+
+func (m Module) Code() *code.Code {
+ return m.code
+}
+
+func (m Module) Deps() []ModuleRef {
+ return m.deps
+}
+
+func (m Module) Globals() []string {
+ return m.globals
+}
+
+func (m Module) IsCore() bool {
+ return m.author == CoreModuleRef.author && m.name == CoreModuleRef.name
+}
+
+func (m Module) GetGlobal(name string) (string, error) {
+ // TODO: Don't use loop
+ found := false
+ for _, global := range m.globals {
+ if global == name {
+ found = true
+ break
+ }
+ }
+
+ if !found {
+ return "", fmt.Errorf("global %s not in module", name)
+ }
+
+ return fmt.Sprintf("%s:%s:%s", m.author, m.name, name), nil
+}
+
+type ModuleRef struct {
+ author string
+ name string
+}
+
+func NewRef(author, name string) ModuleRef {
+ return ModuleRef{
+ author: author,
+ name: name,
+ }
+}
+
+func (m ModuleRef) Author() string {
+ return m.author
+}
+
+func (m ModuleRef) Name() string {
+ return m.name
+}
+
+var (
+ CoreModuleRef = ModuleRef{
+ author: "",
+ name: "core",
+ }
+)
diff --git a/pkg/lang/modules/natives/natives.go b/pkg/lang/modules/natives/natives.go
new file mode 100644
index 0000000..a1b09b6
--- /dev/null
+++ b/pkg/lang/modules/natives/natives.go
@@ -0,0 +1,39 @@
+package natives
+
+import (
+ "jinx/pkg/lang/modules/core"
+ "jinx/pkg/lang/vm/executor"
+)
+
+var Natives = makeNatives(
+ core.Natives,
+)
+
+func makeNatives(moduleNativesArrays ...[]any) []Native {
+ natives := make([]Native, 0)
+
+ for _, moduleNatives := range moduleNativesArrays {
+ for _, moduleNativeI := range moduleNatives {
+ moduleNative := moduleNativeI.(moduleNative)
+
+ natives = append(natives, Native{
+ Name: moduleNative.Name(),
+ ArgCount: moduleNative.ArgCount(),
+ Fn: moduleNative.Fn(),
+ })
+ }
+ }
+ return natives
+}
+
+type Native struct {
+ Name string
+ ArgCount int
+ Fn executor.NativeFunc
+}
+
+type moduleNative interface {
+ Name() string
+ ArgCount() int
+ Fn() executor.NativeFunc
+}