Skip to content

Commit

Permalink
Basic Modules (#22)
Browse files Browse the repository at this point in the history
  • Loading branch information
kritzcreek committed Aug 18, 2024
1 parent 8435804 commit 15929ef
Show file tree
Hide file tree
Showing 48 changed files with 4,250 additions and 2,954 deletions.
81 changes: 71 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ While developing the compiler a couple of other tools are useful/necessary to ha

The easiest way I've found to install them is using [cargo-binstall]:
```sh
cargo binstall just wasm-bindgen-cli wasm-tools wasm-opt
cargo binstall just wasm-bindgen-cli wasm-tools wasm-opt watchexec-cli
```

Additionally you'll need a version of Node > 22.0.0 if you'd like to run the generated Wasm code outside of the browser. (You could probably also make Deno work)
Expand Down
95 changes: 45 additions & 50 deletions crates/backend/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ use std::fmt::Write;

use crate::wasm_builder::{BodyBuilder, Builder};
use frontend::ir::{
Callee, Declaration, DeclarationData, Expr, ExprData, Func, Id, Lit, LitData, Name, NameSupply,
Op, OpData, Pattern, PatternData, Program, SetTarget, SetTargetData, Substitution, Ty, TypeDef,
Callee, Ctx, Declaration, DeclarationData, Expr, ExprData, Func, Lit, LitData, ModuleId, Name,
NameTag, Op, OpData, Pattern, PatternData, Program, SetTarget, SetTargetData, Substitution, Ty,
TypeDef,
};
use text_size::TextRange;
use wasm_encoder::{BlockType, ConstExpr, HeapType, Instruction, RefType, ValType};

pub fn codegen(program: Program, name_supply: NameSupply) -> (Vec<u8>, NameSupply) {
let builder = Builder::new(name_supply);
pub fn codegen(program: Program, ctx: Ctx) -> (Vec<u8>, Ctx) {
let builder = Builder::new(ctx);
let mut codegen = Codegen {
builder,
poly_funcs: HashMap::new(),
Expand Down Expand Up @@ -128,10 +129,10 @@ impl<'a> Codegen<'a> {
fn compile_expr(&mut self, body: &mut BodyBuilder, expr: Expr) -> Vec<Instruction<'a>> {
match *expr.it {
ExprData::Lit { lit } => self.compile_lit(lit),
ExprData::Var { name } => match name {
Name::Local(_) => vec![Instruction::LocalGet(body.lookup_local(&name).unwrap())],
Name::Global(_) => vec![Instruction::GlobalGet(self.builder.lookup_global(&name))],
Name::Func(_) => {
ExprData::Var { name } => match name.tag {
NameTag::Local => vec![Instruction::LocalGet(body.lookup_local(&name).unwrap())],
NameTag::Global => vec![Instruction::GlobalGet(self.builder.lookup_global(&name))],
NameTag::Func => {
let Ty::Func(ty) = &expr.ty else {
unreachable!("Non-function type for function reference")
};
Expand Down Expand Up @@ -291,10 +292,11 @@ impl<'a> Codegen<'a> {
} => {
let mut instrs = vec![];

let gen_name = self.builder.name_supply.local_idx(Id {
it: "$match_scrutinee".to_string(),
at: scrutinee.at,
});
let (gen_name, _) = self.builder.name_supply().local_idx(
ModuleId::CODEGEN,
"$match_scrutinee",
scrutinee.at,
);
let scrutinee_ty = self.builder.val_ty(&scrutinee.ty);
let scrutinee_local = body.new_local(gen_name, scrutinee_ty);
instrs.extend(self.compile_expr(body, scrutinee));
Expand Down Expand Up @@ -393,10 +395,11 @@ impl<'a> Codegen<'a> {
let (func_name, func_idx) = self
.builder
.declare_anon_func(expr.at, closure_info.closure_func_ty);
let env_name = self.builder.name_supply.local_idx(Id {
at: TextRange::empty(0.into()),
it: "env".to_string(),
});
let (env_name, _) = self.builder.name_supply().local_idx(
ModuleId::CODEGEN,
"env",
TextRange::default(),
);
let mut func_params = vec![(
env_name,
ValType::Ref(RefType {
Expand Down Expand Up @@ -582,20 +585,18 @@ impl<'a> Codegen<'a> {
}
SetTargetData::SetVar { name } => {
let mut instrs = self.compile_expr(body, expr);
match name {
Name::Global(_) => {
match name.tag {
NameTag::Global => {
instrs.push(Instruction::GlobalSet(self.builder.lookup_global(&name)));
}
Name::Local(_) => {
NameTag::Local => {
instrs.push(Instruction::LocalSet(body.lookup_local(&name).unwrap()));
}
Name::Func(_)
| Name::Type(_)
| Name::TypeVar(_)
| Name::Field(_)
| Name::Gen(_) => {
unreachable!("can't set a non local/global variable")
}
NameTag::Func
| NameTag::Type
| NameTag::TypeVar
| NameTag::Field
| NameTag::Gen => unreachable!("can't set a non local/global variable"),
};
instrs
}
Expand All @@ -609,24 +610,16 @@ impl<'a> Codegen<'a> {
if let Some(existing) = poly_func.instances.get(&tys) {
return *existing;
}
let definition = self
.builder
.name_supply
.lookup(name)
.expect("Unknown polyfunc");
let mut it = format!("{}#", definition.it);
let func_name = self.builder.ctx.display_name(name);
let mut it = format!("{}#", func_name);
for param in &tys {
write!(
&mut it,
"_{}",
param.display(&self.builder.name_supply.name_map)
)
.unwrap()
write!(&mut it, "_{}", param.display(&self.builder.ctx)).unwrap()
}
let new_name = self.builder.name_supply.func_idx(Id {
it,
at: definition.at,
});
let (new_name, _) = self.builder.name_supply().func_idx(
ModuleId::CODEGEN,
&func_name,
TextRange::default(),
);
poly_func.instances.insert(tys, new_name);
new_name
};
Expand Down Expand Up @@ -703,10 +696,14 @@ impl<'a> Codegen<'a> {
}
}
}
let (start_fn, _) = self.builder.name_supply().func_idx(
ModuleId::CODEGEN,
"start",
TextRange::default(),
);
let start_locals = start_body.get_locals();
self.builder.declare_start(program.start_fn);
self.builder
.fill_func(program.start_fn, start_locals, start_instrs);
self.builder.declare_start(start_fn);
self.builder.fill_func(start_fn, start_locals, start_instrs);
}

for func in program.funcs {
Expand All @@ -722,14 +719,12 @@ impl<'a> Codegen<'a> {
let body = self.compile_expr(&mut body_builder, func.body);
let locals = body_builder.get_locals();
self.builder.fill_func(func.name, locals, body);
self.builder.declare_export(
func.name,
self.builder.resolve_name(func.name).it.to_string(),
);
self.builder
.declare_export(func.name, self.builder.resolve_name(func.name));
}
}

pub fn finish(self) -> (Vec<u8>, NameSupply) {
pub fn finish(self) -> (Vec<u8>, Ctx) {
self.builder.finish()
}
}
Expand Down
22 changes: 8 additions & 14 deletions crates/backend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,16 @@ use frontend::run_frontend;
pub fn compile_program(source: &str) -> Result<Vec<u8>, String> {
let check_result = run_frontend(source);

if !check_result.errors.is_empty() {
for err in &check_result.errors {
eprintln!(
"{}",
err.display(source, &check_result.names.name_map, true)
);
if check_result.has_errors() {
let mut count = 0;
for err in check_result.errors() {
count += 1;
eprintln!("{}", err.display(source, &check_result.ctx, true));
}
return Err(format!(
"Compiling failed with {} errors",
check_result.errors.len()
));
return Err(format!("Compiling failed with {} errors", count));
}

let (wasm, _) = codegen(
check_result.ir.expect("No IR despite no check errors"),
check_result.names,
);
let (ctx, ir) = check_result.consume();
let (wasm, _) = codegen(ir.expect("No IR despite no check errors"), ctx);
Ok(wasm)
}
Loading

0 comments on commit 15929ef

Please sign in to comment.