diff --git a/huia-compiler/src/block.rs b/huia-compiler/src/block.rs index 72581e7..0f52932 100644 --- a/huia-compiler/src/block.rs +++ b/huia-compiler/src/block.rs @@ -23,3 +23,24 @@ impl Block { self.ir } } + +#[derive(Debug, Clone, PartialEq)] +pub struct BlockIdx(usize); + +impl From for BlockIdx { + fn from(i: usize) -> BlockIdx { + BlockIdx(i) + } +} + +impl From for usize { + fn from(i: BlockIdx) -> usize { + i.0 + } +} + +impl From<&BlockIdx> for usize { + fn from(i: &BlockIdx) -> usize { + i.0 + } +} diff --git a/huia-compiler/src/context.rs b/huia-compiler/src/context.rs index bb12828..fa33d29 100644 --- a/huia-compiler/src/context.rs +++ b/huia-compiler/src/context.rs @@ -1,3 +1,4 @@ +use crate::block::{Block, BlockIdx}; use crate::error::CompileError; use crate::function::{Function, FunctionIdx}; use crate::location::Location; @@ -8,6 +9,7 @@ use huia_parser::input_location::InputLocation; #[derive(Debug)] pub struct Context { + blocks: Vec, current_file: StringIdx, errors: Vec, functions: Vec, @@ -19,12 +21,14 @@ pub struct Context { impl Context { pub fn new(path: &str) -> Context { let mut strings = StringTable::default(); + let blocks = Vec::default(); let current_file = strings.intern(path); let errors = Vec::default(); let functions = Vec::default(); let types = Vec::default(); let methods = Vec::default(); Context { + blocks, current_file, errors, functions, @@ -134,6 +138,16 @@ impl Context { self.functions.get(usize::from(idx)) } + pub fn push_block(&mut self, block: Block) -> BlockIdx { + let idx = self.blocks.len(); + self.blocks.push(block); + idx.into() + } + + pub fn get_block(&self, idx: BlockIdx) -> Option<&Block> { + self.blocks.get(usize::from(idx)) + } + #[cfg(test)] pub fn find_type(&mut self, name: &str) -> Option<&Ty> { let name = self.constant_string(name); diff --git a/huia-compiler/src/function.rs b/huia-compiler/src/function.rs index e39348c..e01f21e 100644 --- a/huia-compiler/src/function.rs +++ b/huia-compiler/src/function.rs @@ -1,4 +1,4 @@ -use crate::block::Block; +use crate::block::BlockIdx; use crate::stable::StringIdx; use crate::ty::TyIdx; @@ -16,7 +16,7 @@ impl Function { } } - pub fn push(&mut self, arguments: Vec<(StringIdx, TyIdx)>, block: Block) -> ClauseIdx { + pub fn push(&mut self, arguments: Vec<(StringIdx, TyIdx)>, block: BlockIdx) -> ClauseIdx { let idx = self.clauses.len(); self.clauses.push(Clause::new(arguments, block)); idx.into() @@ -30,11 +30,11 @@ impl Function { #[derive(Debug)] pub struct Clause { arguments: Vec<(StringIdx, TyIdx)>, - body: Block, + body: BlockIdx, } impl Clause { - pub fn new(arguments: Vec<(StringIdx, TyIdx)>, body: Block) -> Clause { + pub fn new(arguments: Vec<(StringIdx, TyIdx)>, body: BlockIdx) -> Clause { Clause { arguments, body } } } @@ -91,7 +91,7 @@ mod test { let mut fun = Function::new(rt); assert!(fun.is_empty()); - fun.push(Vec::new(), Block::default()); + fun.push(Vec::new(), BlockIdx::from(123)); assert!(!fun.is_empty()); } diff --git a/huia-compiler/src/ir/builder.rs b/huia-compiler/src/ir/builder.rs index 6506db0..95295e0 100644 --- a/huia-compiler/src/ir/builder.rs +++ b/huia-compiler/src/ir/builder.rs @@ -8,9 +8,6 @@ use crate::ty::TyIdx; use huia_parser::ast::{Location, NodeType, Term, Value}; /// The Builder is a simple stack machine for converting AST into IR. -/// FIXME: -/// Maybe push a named block somehow when defining types so that we can figure -/// out where we are when building methods, etc. #[derive(Debug)] struct Builder { blocks: Vec, @@ -69,7 +66,7 @@ impl Builder { for node in args { self.build(node.clone(), &mut context); } - let arguments = self.pop_block().unwrap(); + let arguments = self.pop_block().unwrap().ir(); self.push_ir(IR::GetLocal(name)); self.push_ir(IR::Call(arguments)); @@ -139,7 +136,8 @@ impl Builder { } let clause_data = self.pop_block().unwrap(); - fun.push(arguments, clause_data); + let idx = context.push_block(clause_data); + fun.push(arguments, idx); } let fun_idx = context.define_function(fun); @@ -158,14 +156,21 @@ impl Builder { self.build(node.clone(), &mut context); } let positive = self.pop_block().unwrap(); + let positive_idx = context.push_block(positive); self.push_block(); for node in negative { self.build(node.clone(), &mut context); } let negative = self.pop_block().unwrap(); + let negative_idx = context.push_block(negative); - self.push_ir(IR::If(Box::new(test), positive, negative, result_type)); + self.push_ir(IR::If( + Box::new(test), + positive_idx, + negative_idx, + result_type, + )); } NodeType::ImplDef => { let (ty, body) = node.impldef().unwrap(); @@ -291,7 +296,8 @@ impl Builder { self.build(node.clone(), &mut context); } let clause_data = self.pop_block().unwrap(); - method.push(arguments, clause_data); + let idx = context.push_block(clause_data); + method.push(arguments, idx); context.define_method(method); } @@ -344,7 +350,8 @@ impl Builder { self.build(node.clone(), &mut context); } let clause_data = self.pop_block().unwrap(); - method.push(arguments, clause_data); + let idx = context.push_block(clause_data); + method.push(arguments, idx); context.define_method(method); } @@ -397,7 +404,8 @@ impl Builder { self.build(node.clone(), &mut context); } let clause_data = self.pop_block().unwrap(); - method.push(arguments, clause_data); + let idx = context.push_block(clause_data); + method.push(arguments, idx); context.define_method(method); } diff --git a/huia-compiler/src/ir/mod.rs b/huia-compiler/src/ir/mod.rs index 4a89249..82bc8b6 100644 --- a/huia-compiler/src/ir/mod.rs +++ b/huia-compiler/src/ir/mod.rs @@ -1,6 +1,6 @@ mod builder; -use crate::block::Block; +use crate::block::BlockIdx; use crate::function::FunctionIdx; use crate::stable::StringIdx; use crate::ty::TyIdx; @@ -14,7 +14,7 @@ use huia_parser::ast::unary::Operator as UnOp; #[derive(Debug, PartialEq)] pub enum IR { /// Call top of the stack with arguments. - Call(Block), + Call(Vec), /// A constant value of the specified type. Constant(TyIdx, Val), /// Construct an instance of type with the provided properties. @@ -26,7 +26,7 @@ pub enum IR { /// Refernce an instance property. GetProperty(StringIdx), /// Consists of test, positives, negatives and a return type. - If(Box, Block, Block, TyIdx), + If(Box, BlockIdx, BlockIdx, TyIdx), /// A binary operation with LHS and RHS. Infix(BinOp, Box<(IR, IR)>), /// Take a value and set it as a local variable. diff --git a/huia-compiler/src/method.rs b/huia-compiler/src/method.rs index e65b6d8..c9a538e 100644 --- a/huia-compiler/src/method.rs +++ b/huia-compiler/src/method.rs @@ -1,4 +1,4 @@ -use crate::block::Block; +use crate::block::BlockIdx; use crate::function::{Clause, ClauseIdx}; use crate::stable::StringIdx; use crate::ty::TyIdx; @@ -43,7 +43,7 @@ impl Method { } } - pub fn push(&mut self, arguments: Vec<(StringIdx, TyIdx)>, block: Block) -> ClauseIdx { + pub fn push(&mut self, arguments: Vec<(StringIdx, TyIdx)>, block: BlockIdx) -> ClauseIdx { let idx = self.clauses.len(); self.clauses.push(Clause::new(arguments, block)); idx.into()