about summary refs log tree commit diff
path: root/pkg/lang/modules
diff options
context:
space:
mode:
authorMel <einebeere@gmail.com>2022-08-11 01:25:47 +0000
committerMel <einebeere@gmail.com>2022-08-11 01:25:47 +0000
commit86f31acf6789be116dcc54ed85b069a37c0f7aa8 (patch)
treebc7afd6a8c340825996d29c6cfd392ae42b4fbd5 /pkg/lang/modules
parentc46b2bc7ce6df1f2c6c9494ef08015ec29992da5 (diff)
downloadjinx-86f31acf6789be116dcc54ed85b069a37c0f7aa8.tar.zst
jinx-86f31acf6789be116dcc54ed85b069a37c0f7aa8.zip
Actual modules and core
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
+}