Compile (but not run) imports

This commit is contained in:
Andrew Morris
2023-03-08 11:12:53 +11:00
parent db2f2d4125
commit 8e44cb2e95
12 changed files with 146 additions and 31 deletions

View File

@@ -1,5 +1,6 @@
export @f1 {}
@f1 = function(%a, %b, %c) {
op* %b %c %_tmp0
op+ %a %_tmp0 %return
}
}

View File

@@ -1,4 +1,6 @@
export void { "f2": @f2 }
@f2 = function() {
op++ %this
}
@f2 = function(%x) {
op++ %x
mov %x %return
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -1,5 +1,4 @@
/// <reference path="../../vs.d.ts" />
export function f2(this: number) {
vs.inc(this);
export function f2(x: number) {
x++;
return x;
}

View File

@@ -1,12 +1,10 @@
/// <reference path="../../vs.d.ts" />
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)];
}

View File

@@ -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,
}
}
}

View File

@@ -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);
}

View File

@@ -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,