From 8e44cb2e954d6253170f7eb366bd401e7cb3ff73 Mon Sep 17 00:00:00 2001 From: Andrew Morris Date: Wed, 8 Mar 2023 11:12:53 +1100 Subject: [PATCH] Compile (but not run) imports --- concept-code/modules/compiled/f1.vsm | 3 +- concept-code/modules/compiled/f2.vsm | 8 +- concept-code/modules/compiled/main.vsm | 12 ++- .../modules/compiled/main_optimized.vsm | 12 ++- concept-code/modules/compiled/util.vsm | 3 +- concept-code/modules/linked/main.vsm | 13 ++- .../modules/linked/main_optimized.vsm | 13 ++- concept-code/modules/src/f2.ts | 7 +- concept-code/modules/src/main.ts | 4 +- valuescript_compiler/src/asm.rs | 10 +++ valuescript_compiler/src/assembler.rs | 4 +- valuescript_compiler/src/module_compiler.rs | 88 ++++++++++++++++++- 12 files changed, 146 insertions(+), 31 deletions(-) diff --git a/concept-code/modules/compiled/f1.vsm b/concept-code/modules/compiled/f1.vsm index db1f350..f160922 100644 --- a/concept-code/modules/compiled/f1.vsm +++ b/concept-code/modules/compiled/f1.vsm @@ -1,5 +1,6 @@ export @f1 {} + @f1 = function(%a, %b, %c) { op* %b %c %_tmp0 op+ %a %_tmp0 %return -} +} \ No newline at end of file diff --git a/concept-code/modules/compiled/f2.vsm b/concept-code/modules/compiled/f2.vsm index cc27141..951c25b 100644 --- a/concept-code/modules/compiled/f2.vsm +++ b/concept-code/modules/compiled/f2.vsm @@ -1,4 +1,6 @@ export void { "f2": @f2 } -@f2 = function() { - op++ %this -} + +@f2 = function(%x) { + op++ %x + mov %x %return +} \ No newline at end of file diff --git a/concept-code/modules/compiled/main.vsm b/concept-code/modules/compiled/main.vsm index 5bb70f4..16147e6 100644 --- a/concept-code/modules/compiled/main.vsm +++ b/concept-code/modules/compiled/main.vsm @@ -1,17 +1,21 @@ export @main {} + @f1 = lazy { import "./f1.vsm" %return } + @f2 = lazy { - import_star "./f2.vsm" %return + import* "./f2.vsm" %return sub %return "f2" %return } + @util = lazy { - import_star "./util.vsm" %return + import* "./util.vsm" %return } + @main = function() { call @f1 [1, 2, 3] %x - apply @f2 %x [] %ignore + call @f2 [%x] %x subcall @util "dist" [3, 4] %dist mov [%x, %dist] %return -} +} \ No newline at end of file diff --git a/concept-code/modules/compiled/main_optimized.vsm b/concept-code/modules/compiled/main_optimized.vsm index ec71a39..9b56935 100644 --- a/concept-code/modules/compiled/main_optimized.vsm +++ b/concept-code/modules/compiled/main_optimized.vsm @@ -1,18 +1,22 @@ export @main {} + @f1 = lazy { import "./f1.vsm" %return } + @f2 = lazy { - import_star "./f2.vsm" %return + import* "./f2.vsm" %return sub %return "f2" %return } + @util_dist = lazy { - import_star "./util.vsm" %return + import* "./util.vsm" %return sub %return "dist" %return } + @main = function() { call @f1 [1, 2, 3] %x - apply @f2 %x [] %ignore + call @f2 [%x] %x call @util_dist [3, 4] %dist mov [%x, %dist] %return -} +} \ No newline at end of file diff --git a/concept-code/modules/compiled/util.vsm b/concept-code/modules/compiled/util.vsm index 01885e6..5843e11 100644 --- a/concept-code/modules/compiled/util.vsm +++ b/concept-code/modules/compiled/util.vsm @@ -1,7 +1,8 @@ export void { "dist": @dist } + @dist = function(%x, %y) { op* %x %x %_tmp0 op* %y %y %_tmp1 op+ %_tmp0 %_tmp1 %_tmp1 subcall $Math "sqrt" [%_tmp1] %return -} +} \ No newline at end of file diff --git a/concept-code/modules/linked/main.vsm b/concept-code/modules/linked/main.vsm index edb8b60..9d1de0e 100644 --- a/concept-code/modules/linked/main.vsm +++ b/concept-code/modules/linked/main.vsm @@ -1,21 +1,26 @@ export @main { "main": @main } + @main = function() { call @f1_default [1, 2, 3] %x - apply @f2_f2 %x [] %ignore + call @f2_f2 [%x] %x subcall @util_star "dist" [3, 4] %dist mov [%x, %dist] %return } + @f1_default = function(%a, %b, %c) { op* %b %c %_tmp0 op+ %a %_tmp0 %return } -@f2_f2 = function() { - op++ %this + +@f2_f2 = function(%x) { + op++ %x } + @util_star = { "dist": @util_dist } + @util_dist = function(%x, %y) { op* %x %x %_tmp0 op* %y %y %_tmp1 op+ %_tmp0 %_tmp1 %_tmp1 subcall $Math "sqrt" [%_tmp1] %return -} +} \ No newline at end of file diff --git a/concept-code/modules/linked/main_optimized.vsm b/concept-code/modules/linked/main_optimized.vsm index a1fd5f8..78c7e1f 100644 --- a/concept-code/modules/linked/main_optimized.vsm +++ b/concept-code/modules/linked/main_optimized.vsm @@ -1,20 +1,25 @@ export @main { "main": @main } + @main = function() { call @f1_default [1, 2, 3] %x - apply @f2_f2 %x [] %ignore + call @f2_f2 [%x] %x call @util_dist [3, 4] %dist mov [%x, %dist] %return } + @f1_default = function(%a, %b, %c) { op* %b %c %_tmp0 op+ %a %_tmp0 %return } -@f2_f2 = function() { - op++ %this + +@f2_f2 = function(%x) { + op++ %x + mov %x %return } + @util_dist = function(%x, %y) { op* %x %x %_tmp0 op* %y %y %_tmp1 op+ %_tmp0 %_tmp1 %_tmp1 subcall $Math "sqrt" [%_tmp1] %return -} +} \ No newline at end of file diff --git a/concept-code/modules/src/f2.ts b/concept-code/modules/src/f2.ts index c03f52b..09b7f62 100644 --- a/concept-code/modules/src/f2.ts +++ b/concept-code/modules/src/f2.ts @@ -1,5 +1,4 @@ -/// - -export function f2(this: number) { - vs.inc(this); +export function f2(x: number) { + x++; + return x; } diff --git a/concept-code/modules/src/main.ts b/concept-code/modules/src/main.ts index 7aff97d..70f6335 100644 --- a/concept-code/modules/src/main.ts +++ b/concept-code/modules/src/main.ts @@ -1,12 +1,10 @@ -/// - import f1 from "./f1.ts"; import { f2 } from "./f2.ts"; import * as util from "./util.ts"; export default function main() { let x = f1(1, 2, 3); - vs.apply(f2, x, []); + x = f2(x); return [x, util.dist(3, 4)]; } diff --git a/valuescript_compiler/src/asm.rs b/valuescript_compiler/src/asm.rs index b2996a9..5410118 100644 --- a/valuescript_compiler/src/asm.rs +++ b/valuescript_compiler/src/asm.rs @@ -279,6 +279,8 @@ pub enum Instruction { UnaryPlus(Value, Register), UnaryMinus(Value, Register), New(Value, Value, Register), + Import(Value, Register), + ImportStar(Value, Register), } impl std::fmt::Display for Instruction { @@ -408,6 +410,12 @@ impl std::fmt::Display for Instruction { Instruction::New(value, args, register) => { write!(f, "new {} {} {}", value, args, register) } + Instruction::Import(value, register) => { + write!(f, "import {} {}", value, register) + } + Instruction::ImportStar(value, register) => { + write!(f, "import* {} {}", value, register) + } } } } @@ -462,6 +470,8 @@ impl Instruction { UnaryPlus(..) => 0x29, UnaryMinus(..) => 0x2a, New(..) => 0x2b, + Import(..) => 0x2c, + ImportStar(..) => 0x2d, } } } diff --git a/valuescript_compiler/src/assembler.rs b/valuescript_compiler/src/assembler.rs index ea3dcd6..ed8aabc 100644 --- a/valuescript_compiler/src/assembler.rs +++ b/valuescript_compiler/src/assembler.rs @@ -164,7 +164,9 @@ impl Assembler { | OpBitNot(arg, dst) | TypeOf(arg, dst) | UnaryPlus(arg, dst) - | UnaryMinus(arg, dst) => { + | UnaryMinus(arg, dst) + | Import(arg, dst) + | ImportStar(arg, dst) => { self.value(arg); self.register(dst); } diff --git a/valuescript_compiler/src/module_compiler.rs b/valuescript_compiler/src/module_compiler.rs index c262454..8ea0ced 100644 --- a/valuescript_compiler/src/module_compiler.rs +++ b/valuescript_compiler/src/module_compiler.rs @@ -8,8 +8,8 @@ use swc_ecma_ast::EsVersion; use swc_ecma_parser::{Syntax, TsConfig}; use crate::asm::{ - Class, Definition, DefinitionContent, Function, Instruction, InstructionOrLabel, Module, Object, - Pointer, Register, Value, + Class, Definition, DefinitionContent, Function, Instruction, InstructionOrLabel, Lazy, Module, + Object, Pointer, Register, Value, }; use super::diagnostic::{Diagnostic, DiagnosticLevel}; @@ -311,6 +311,7 @@ impl ModuleCompiler { match module_decl { ExportDefaultDecl(edd) => self.compile_export_default_decl(edd, scope), ExportDecl(ed) => self.compile_export_decl(ed, scope), + Import(import) => self.compile_import(import, scope), _ => self.todo(module_decl.span(), "non-export default module declaration"), } } @@ -455,6 +456,89 @@ impl ModuleCompiler { }; } + fn compile_import(&mut self, import: &swc_ecma_ast::ImportDecl, scope: &Scope) { + let import_path = import.src.value.to_string(); + + for specifier in &import.specifiers { + use swc_ecma_ast::ImportSpecifier::*; + use swc_ecma_ast::ModuleExportName; + + match specifier { + Named(named) => { + let local_name = named.local.sym.to_string(); + + let external_name = match &named.imported { + Some(ModuleExportName::Ident(ident)) => ident.sym.to_string(), + Some(ModuleExportName::Str(str_)) => { + self.todo( + str_.span, + "importing a module export by string (is this a real thing?)", + ); + + "_todo_import_string".to_string() + } + None => local_name.clone(), + }; + + let pointer = scope + .get_defn(&local_name) + .expect("imported name should have been in scope"); + + self.module.definitions.push(Definition { + pointer, + content: DefinitionContent::Lazy(Lazy { + body: vec![ + InstructionOrLabel::Instruction(Instruction::ImportStar( + Value::String(import_path.clone()), + Register::Return, + )), + InstructionOrLabel::Instruction(Instruction::Sub( + Value::Register(Register::Return), + Value::String(external_name), + Register::Return, + )), + ], + }), + }); + } + Default(default) => { + let local_name = default.local.sym.to_string(); + + let pointer = scope + .get_defn(&local_name) + .expect("imported name should have been in scope"); + + self.module.definitions.push(Definition { + pointer, + content: DefinitionContent::Lazy(Lazy { + body: vec![InstructionOrLabel::Instruction(Instruction::Import( + Value::String(import_path.clone()), + Register::Return, + ))], + }), + }); + } + Namespace(namespace) => { + let local_name = namespace.local.sym.to_string(); + + let pointer = scope + .get_defn(&local_name) + .expect("imported name should have been in scope"); + + self.module.definitions.push(Definition { + pointer, + content: DefinitionContent::Lazy(Lazy { + body: vec![InstructionOrLabel::Instruction(Instruction::ImportStar( + Value::String(import_path.clone()), + Register::Return, + ))], + }), + }); + } + } + } + } + fn compile_fn( &mut self, defn_pointer: Pointer,