[fine] Working on rebuilding declarations
Running into walls dealing with imported declarations, thinking maybe this structure will help me.
This commit is contained in:
parent
f3a8203be3
commit
2c03989da3
3 changed files with 277 additions and 334 deletions
|
|
@ -3,7 +3,7 @@ use std::rc::Rc;
|
|||
|
||||
use crate::{
|
||||
parser::{Child, SyntaxTree, Tree, TreeKind, TreeRef},
|
||||
semantics::{string_constant_to_string, Declaration, Location, Semantics, Type},
|
||||
semantics::{string_constant_to_string, Declaration, Location, Origin, Semantics, Type},
|
||||
tokens::TokenKind,
|
||||
};
|
||||
|
||||
|
|
@ -584,38 +584,33 @@ fn compile_binary_expression(c: &mut Compiler, t: TreeRef, tr: &Tree) -> CR {
|
|||
_ => return Err("unsupported lval expression"),
|
||||
};
|
||||
|
||||
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)
|
||||
}
|
||||
Location::Slot => {
|
||||
compile_expression(c, ltree.nth_tree(0).ok_or("no obj lhs")?);
|
||||
Instruction::StoreSlot(index)
|
||||
}
|
||||
// TODO: Handle storage to non-local module.
|
||||
|
||||
let index = declaration.index;
|
||||
let instruction = match declaration.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)
|
||||
}
|
||||
Location::Slot => {
|
||||
compile_expression(c, ltree.nth_tree(0).ok_or("no obj lhs")?);
|
||||
Instruction::StoreSlot(index)
|
||||
}
|
||||
|
||||
Declaration::ExternFunction { .. } => c.inst_panic("store ext"),
|
||||
Declaration::Function { .. } => c.inst_panic("store func"),
|
||||
Declaration::Class { .. } => c.inst_panic("store class"),
|
||||
Declaration::ImportedModule { .. } => c.inst_panic("store import"),
|
||||
Declaration::ImportedDeclaration { .. } => c.inst_panic("store import decl"),
|
||||
Location::ExternalFunction
|
||||
| Location::Function
|
||||
| Location::Class
|
||||
| Location::Import => c.inst_panic("store to invalid location"),
|
||||
};
|
||||
c.push(instruction);
|
||||
OK
|
||||
|
|
@ -638,41 +633,42 @@ fn compile_identifier_expression(c: &mut Compiler, t: TreeRef, tree: &Tree) -> C
|
|||
}
|
||||
|
||||
fn compile_load_declaration(c: &mut Compiler, t: TreeRef, declaration: &Declaration) -> CR {
|
||||
let instruction = match declaration {
|
||||
Declaration::Variable {
|
||||
location, index, ..
|
||||
} => {
|
||||
let index = *index;
|
||||
match location {
|
||||
Location::Local => {
|
||||
if index >= c.function.locals {
|
||||
c.function.locals = index + 1;
|
||||
}
|
||||
Instruction::LoadLocal(index)
|
||||
}
|
||||
Location::Argument => {
|
||||
compiler_assert!(c, t, index < c.function.args);
|
||||
Instruction::LoadArgument(index)
|
||||
}
|
||||
Location::Module => {
|
||||
compiler_assert!(c, t, index < c.module.globals);
|
||||
Instruction::LoadModule(index)
|
||||
}
|
||||
Location::Slot => {
|
||||
// TODO: Assert slot is in field range?
|
||||
Instruction::LoadSlot(index)
|
||||
}
|
||||
// TODO: Handle load of non-local value.
|
||||
|
||||
let index = declaration.index;
|
||||
let instruction = match declaration.location {
|
||||
Location::Local => {
|
||||
if index >= c.function.locals {
|
||||
c.function.locals = index + 1;
|
||||
}
|
||||
Instruction::LoadLocal(index)
|
||||
}
|
||||
Declaration::Function { declaration, .. } => {
|
||||
let key = FunctionKey { tree: *declaration };
|
||||
Location::Argument => {
|
||||
compiler_assert!(c, t, index < c.function.args);
|
||||
Instruction::LoadArgument(index)
|
||||
}
|
||||
Location::Module => {
|
||||
compiler_assert!(c, t, index < c.module.globals);
|
||||
Instruction::LoadModule(index)
|
||||
}
|
||||
Location::Slot => {
|
||||
// TODO: Assert slot is in field range?
|
||||
Instruction::LoadSlot(index)
|
||||
}
|
||||
|
||||
Location::Function => {
|
||||
// TODO: Assert declaration is local
|
||||
let Origin::Source(ft) = declaration.origin else {
|
||||
ice!(c, t, "Function location but external origin?");
|
||||
};
|
||||
let key = FunctionKey { tree: ft };
|
||||
let index = match c.function_bindings.get(&key) {
|
||||
Some(index) => *index,
|
||||
None => {
|
||||
let tree = &c.syntax[*declaration];
|
||||
let tree = &c.syntax[ft];
|
||||
compiler_assert_eq!(c, t, tree.kind, TreeKind::FunctionDecl);
|
||||
|
||||
compile_function_declaration(c, *declaration, tree, false)?;
|
||||
compile_function_declaration(c, ft, tree, false)?;
|
||||
|
||||
match c.function_bindings.get(&key) {
|
||||
Some(index) => *index,
|
||||
|
|
@ -689,14 +685,14 @@ fn compile_load_declaration(c: &mut Compiler, t: TreeRef, declaration: &Declarat
|
|||
};
|
||||
Instruction::LoadFunction(index)
|
||||
}
|
||||
Declaration::ExternFunction { id, .. } => Instruction::LoadExternFunction(id.id()),
|
||||
|
||||
Location::ExternalFunction => Instruction::LoadExternFunction(index),
|
||||
|
||||
// Must be a static don't worry about it.
|
||||
Declaration::Class { .. } => return OK,
|
||||
Location::Class => return OK,
|
||||
|
||||
// fix later
|
||||
Declaration::ImportedModule { .. } => ice!(c, t, "import compile not supported"),
|
||||
Declaration::ImportedDeclaration { .. } => ice!(c, t, "import decl not supported"),
|
||||
Location::Import => ice!(c, t, "import compile not supported"),
|
||||
};
|
||||
|
||||
c.push(instruction);
|
||||
|
|
@ -766,14 +762,12 @@ fn compile_pattern(c: &mut Compiler, t: TreeRef) -> CR {
|
|||
ice!(c, t, "cannot bind pattern variable `{id}`");
|
||||
};
|
||||
|
||||
let Declaration::Variable {
|
||||
location: Location::Local,
|
||||
index,
|
||||
..
|
||||
} = declaration
|
||||
else {
|
||||
ice!(c, t, "is cannot make a non-local, non-variable declaration")
|
||||
};
|
||||
compiler_assert!(
|
||||
c,
|
||||
t,
|
||||
declaration.location == Location::Local,
|
||||
"is cannot make a non-local, non-variable declaration"
|
||||
);
|
||||
|
||||
// If we aren't a wildcard or we have an attached predicate then
|
||||
// we will need the value on the stack, otherwise we can discard
|
||||
|
|
@ -781,7 +775,7 @@ fn compile_pattern(c: &mut Compiler, t: TreeRef) -> CR {
|
|||
if and_index.is_some() || !is_wildcard {
|
||||
c.push(Instruction::Dup);
|
||||
}
|
||||
c.push(Instruction::StoreLocal(*index));
|
||||
c.push(Instruction::StoreLocal(declaration.index));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -857,11 +851,17 @@ fn compile_type_identifier_eq(c: &mut Compiler, t: TreeRef, tree: &Tree) -> CR {
|
|||
}
|
||||
_ => {
|
||||
let environment = c.semantics.environment_of(t);
|
||||
match environment.bind(identifier).ok_or("cannot bind")? {
|
||||
Declaration::Class { declaration, .. } => {
|
||||
// The runtime identifier of the class is the tree index of the
|
||||
// class declaration sure why not.
|
||||
let index = declaration.index();
|
||||
let declaration = environment.bind(identifier).ok_or("cannot bind")?;
|
||||
match declaration.location {
|
||||
Location::Class => {
|
||||
// TODO: Handle non-local class declaration!
|
||||
|
||||
// The runtime identifier of the class is the tree index
|
||||
// of the class declaration sure why not.
|
||||
let Origin::Source(classdecl) = declaration.origin else {
|
||||
ice!(c, t, "This class declaration doesn't have an origin");
|
||||
};
|
||||
let index = classdecl.index();
|
||||
c.push(Instruction::IsClass(index.try_into().unwrap()));
|
||||
}
|
||||
|
||||
|
|
@ -985,13 +985,17 @@ fn compile_new_object_expression(c: &mut Compiler, t: TreeRef, tree: &Tree) -> C
|
|||
.ok_or("no type id")?
|
||||
.as_str(&c.source);
|
||||
let environment = c.semantics.environment_of(t);
|
||||
match environment.bind(identifier).ok_or("cannot bind type")? {
|
||||
Declaration::Class { declaration, .. } => {
|
||||
let key = FunctionKey { tree: *declaration };
|
||||
let declaration = environment.bind(identifier).ok_or("cannot bind type")?;
|
||||
match declaration.location {
|
||||
Location::Class => {
|
||||
let Origin::Source(classdecl) = declaration.origin else {
|
||||
ice!(c, t, "this class declaration has no source?");
|
||||
};
|
||||
let key = FunctionKey { tree: classdecl };
|
||||
let index = match c.function_bindings.get(&key) {
|
||||
Some(index) => *index,
|
||||
None => {
|
||||
let tree = &c.syntax[*declaration];
|
||||
let tree = &c.syntax[classdecl];
|
||||
compiler_assert_eq!(c, t, tree.kind, TreeKind::ClassDecl);
|
||||
|
||||
compile_class_declaration(c, t, tree, false)?;
|
||||
|
|
@ -1146,15 +1150,10 @@ fn compile_let_statement(c: &mut Compiler, t: TreeRef, tree: &Tree, gen_value: b
|
|||
.bind(tree.nth_token(1).ok_or("no id")?.as_str(&c.source))
|
||||
.ok_or("cannot bind")?;
|
||||
|
||||
let Declaration::Variable {
|
||||
location, index, ..
|
||||
} = declaration
|
||||
else {
|
||||
ice!(c, t, "let cannot make a non-variable declaration")
|
||||
};
|
||||
// TODO: ASSERT LOCAL DECLARATION?
|
||||
|
||||
let index = *index;
|
||||
let instruction = match location {
|
||||
let index = declaration.index;
|
||||
let instruction = match declaration.location {
|
||||
Location::Local => {
|
||||
if index >= c.function.locals {
|
||||
c.function.locals = index + 1;
|
||||
|
|
@ -1314,22 +1313,15 @@ fn compile_for_statement(c: &mut Compiler, tree: &Tree, gen_value: bool) -> CR {
|
|||
let Some(variable_decl) = env.bind(id) else {
|
||||
ice!(c, body, "Unable to bind {id} in loop body");
|
||||
};
|
||||
let variable_slot = match variable_decl {
|
||||
Declaration::Variable {
|
||||
location, index, ..
|
||||
} => {
|
||||
compiler_assert_eq!(
|
||||
c,
|
||||
vt,
|
||||
*location,
|
||||
Location::Local,
|
||||
"expected loop variable to be local"
|
||||
);
|
||||
|
||||
*index
|
||||
}
|
||||
_ => ice!(c, vt, "loop variable was not a variable"),
|
||||
};
|
||||
compiler_assert_eq!(
|
||||
c,
|
||||
vt,
|
||||
variable_decl.location,
|
||||
Location::Local,
|
||||
"expected loop variable to be local"
|
||||
);
|
||||
let variable_slot = variable_decl.index;
|
||||
|
||||
// Figure out the generator.
|
||||
let iterable = tree.nth_tree(3).ok_or("no generator")?;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue