[fine] Assignments!
And new error capabilities!
This commit is contained in:
parent
92cf840766
commit
f20f5a5e03
12 changed files with 400 additions and 64 deletions
|
|
@ -14,6 +14,10 @@ pub enum Instruction {
|
|||
Panic,
|
||||
|
||||
BoolNot,
|
||||
Call(usize),
|
||||
CompareBool,
|
||||
CompareFloat,
|
||||
CompareString,
|
||||
Discard,
|
||||
FloatAdd,
|
||||
FloatDivide,
|
||||
|
|
@ -23,6 +27,8 @@ pub enum Instruction {
|
|||
JumpFalse(usize),
|
||||
JumpTrue(usize),
|
||||
LoadArgument(usize),
|
||||
LoadExternFunction(usize), // NOTE: FUNKY, might want to indirect this index.
|
||||
LoadFunction(usize),
|
||||
LoadLocal(usize),
|
||||
LoadModule(usize),
|
||||
PushFalse,
|
||||
|
|
@ -30,16 +36,12 @@ pub enum Instruction {
|
|||
PushNothing,
|
||||
PushString(usize),
|
||||
PushTrue,
|
||||
Return,
|
||||
StoreArgument(usize),
|
||||
StoreLocal(usize),
|
||||
StoreModule(usize),
|
||||
LoadFunction(usize),
|
||||
LoadExternFunction(usize), // NOTE: FUNKY, might want to indirect this index.
|
||||
Call(usize),
|
||||
Return,
|
||||
StringAdd,
|
||||
CompareBool,
|
||||
CompareString,
|
||||
CompareFloat,
|
||||
Dup,
|
||||
}
|
||||
|
||||
pub enum Export {
|
||||
|
|
@ -372,30 +374,41 @@ fn compile_condition_expression(c: &mut Compiler, t: &Tree) -> CR {
|
|||
OK
|
||||
}
|
||||
|
||||
fn compile_binary_expression(c: &mut Compiler, t: TreeRef, tr: &Tree) -> CR {
|
||||
fn compile_simple_binary_expression<T>(c: &mut Compiler, tr: &Tree, f: T) -> CR
|
||||
where
|
||||
T: FnOnce(&mut Compiler, &Type) -> Instruction,
|
||||
{
|
||||
compile_expression(c, tr.nth_tree(0)?);
|
||||
|
||||
let arg_tree = tr.nth_tree(2)?;
|
||||
let arg_type = c.semantics.type_of(arg_tree);
|
||||
|
||||
compile_expression(c, arg_tree);
|
||||
|
||||
let inst = f(c, &arg_type);
|
||||
c.push(inst);
|
||||
|
||||
OK
|
||||
}
|
||||
|
||||
fn compile_binary_expression(c: &mut Compiler, t: TreeRef, tr: &Tree) -> CR {
|
||||
match tr.nth_token(1)?.kind {
|
||||
TokenKind::Plus => {
|
||||
compile_expression(c, tr.nth_tree(2)?);
|
||||
c.push(match c.semantics.type_of(t) {
|
||||
Type::F64 => Instruction::FloatAdd,
|
||||
Type::String => Instruction::StringAdd,
|
||||
_ => Instruction::Panic,
|
||||
});
|
||||
}
|
||||
TokenKind::Plus => compile_simple_binary_expression(c, tr, |_, t| match t {
|
||||
Type::F64 => Instruction::FloatAdd,
|
||||
Type::String => Instruction::StringAdd,
|
||||
_ => Instruction::Panic,
|
||||
}),
|
||||
TokenKind::Minus => {
|
||||
compile_expression(c, tr.nth_tree(2)?);
|
||||
c.push(Instruction::FloatSubtract);
|
||||
compile_simple_binary_expression(c, tr, |_, _| Instruction::FloatSubtract)
|
||||
}
|
||||
TokenKind::Star => {
|
||||
compile_expression(c, tr.nth_tree(2)?);
|
||||
c.push(Instruction::FloatMultiply);
|
||||
compile_simple_binary_expression(c, tr, |_, _| Instruction::FloatMultiply)
|
||||
}
|
||||
TokenKind::Slash => {
|
||||
compile_expression(c, tr.nth_tree(2)?);
|
||||
c.push(Instruction::FloatDivide);
|
||||
compile_simple_binary_expression(c, tr, |_, _| Instruction::FloatDivide)
|
||||
}
|
||||
TokenKind::And => {
|
||||
compile_expression(c, tr.nth_tree(0)?);
|
||||
let jump_false_index = c.push(Instruction::JumpFalse(0));
|
||||
|
||||
c.push(Instruction::PushTrue);
|
||||
|
|
@ -406,8 +419,10 @@ fn compile_binary_expression(c: &mut Compiler, t: TreeRef, tr: &Tree) -> CR {
|
|||
compile_expression(c, tr.nth_tree(2)?);
|
||||
|
||||
c.patch(jump_end_index, |i| Instruction::Jump(i));
|
||||
OK
|
||||
}
|
||||
TokenKind::Or => {
|
||||
compile_expression(c, tr.nth_tree(0)?);
|
||||
let jump_true_index = c.push(Instruction::JumpTrue(0));
|
||||
|
||||
c.push(Instruction::PushTrue);
|
||||
|
|
@ -418,29 +433,70 @@ fn compile_binary_expression(c: &mut Compiler, t: TreeRef, tr: &Tree) -> CR {
|
|||
compile_expression(c, tr.nth_tree(2)?);
|
||||
|
||||
c.patch(jump_end_index, |i| Instruction::Jump(i));
|
||||
OK
|
||||
}
|
||||
TokenKind::EqualEqual => {
|
||||
let arg_tree = tr.nth_tree(2)?;
|
||||
let arg_type = c.semantics.type_of(arg_tree);
|
||||
|
||||
compile_simple_binary_expression(c, tr, |c, arg_type| {
|
||||
if c.semantics.type_compat(&arg_type, &Type::Nothing) {
|
||||
c.push(Instruction::Discard);
|
||||
c.push(Instruction::Discard);
|
||||
Instruction::PushTrue
|
||||
} else {
|
||||
match arg_type {
|
||||
Type::F64 => Instruction::CompareFloat,
|
||||
Type::String => Instruction::CompareString,
|
||||
Type::Bool => Instruction::CompareBool, // ?
|
||||
_ => Instruction::Panic,
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
TokenKind::Equal => {
|
||||
compile_expression(c, tr.nth_tree(2)?);
|
||||
c.push(Instruction::Dup);
|
||||
|
||||
if c.semantics.type_compat(&arg_type, &Type::Nothing) {
|
||||
c.push(Instruction::Discard);
|
||||
c.push(Instruction::Discard);
|
||||
c.push(Instruction::PushTrue);
|
||||
} else {
|
||||
c.push(match arg_type {
|
||||
Type::F64 => Instruction::CompareFloat,
|
||||
Type::String => Instruction::CompareString,
|
||||
Type::Bool => Instruction::CompareBool, // ?
|
||||
_ => Instruction::Panic,
|
||||
});
|
||||
let lvalue = tr.nth_tree(0)?;
|
||||
let ltree = &c.syntax[lvalue];
|
||||
match ltree.kind {
|
||||
TreeKind::Identifier => {
|
||||
let ident = ltree.nth_token(0)?;
|
||||
let environment = c.semantics.environment_of(lvalue);
|
||||
let declaration = environment.bind(ident)?;
|
||||
|
||||
let instruction = match declaration {
|
||||
Declaration::Variable {
|
||||
location, index, ..
|
||||
} => {
|
||||
let index = *index;
|
||||
match location {
|
||||
Location::Argument => {
|
||||
compiler_assert!(c, t, index < c.function.args);
|
||||
Instruction::StoreArgument(index)
|
||||
}
|
||||
Location::Local => {
|
||||
if index >= c.function.locals {
|
||||
c.function.locals = index + 1;
|
||||
}
|
||||
Instruction::StoreLocal(index)
|
||||
}
|
||||
Location::Module => {
|
||||
compiler_assert!(c, t, index < c.module.globals);
|
||||
Instruction::StoreModule(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Declaration::ExternFunction { .. } => Instruction::Panic,
|
||||
Declaration::Function { .. } => Instruction::Panic,
|
||||
};
|
||||
c.push(instruction);
|
||||
}
|
||||
_ => ice!(c, t, "Unsupported lvalue type"),
|
||||
}
|
||||
OK
|
||||
}
|
||||
_ => ice!(c, t, "Unsupported binary expression"),
|
||||
}
|
||||
OK
|
||||
}
|
||||
|
||||
fn compile_identifier_expression(c: &mut Compiler, t: TreeRef, tree: &Tree) -> Option<()> {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue