[fine] Imports maybe
Feels a little sketchy
This commit is contained in:
parent
1199646e29
commit
60e8f64c01
4 changed files with 299 additions and 85 deletions
|
|
@ -582,7 +582,8 @@ fn compile_binary_expression(c: &mut Compiler, t: TreeRef, tr: &Tree) -> CR {
|
|||
Declaration::ExternFunction { .. } => inst_panic!("store ext"),
|
||||
Declaration::Function { .. } => inst_panic!("store func"),
|
||||
Declaration::Class { .. } => inst_panic!("store class"),
|
||||
Declaration::Import { .. } => inst_panic!("store import"),
|
||||
Declaration::ImportedModule { .. } => inst_panic!("store import"),
|
||||
Declaration::ImportedDeclaration { .. } => inst_panic!("store import decl"),
|
||||
};
|
||||
c.push(instruction);
|
||||
OK
|
||||
|
|
@ -662,7 +663,8 @@ fn compile_load_declaration(c: &mut Compiler, t: TreeRef, declaration: &Declarat
|
|||
Declaration::Class { .. } => return OK,
|
||||
|
||||
// fix later
|
||||
Declaration::Import { .. } => ice!(c, t, "import compile not supported"),
|
||||
Declaration::ImportedModule { .. } => ice!(c, t, "import compile not supported"),
|
||||
Declaration::ImportedDeclaration { .. } => ice!(c, t, "import decl not supported"),
|
||||
};
|
||||
|
||||
c.push(instruction);
|
||||
|
|
@ -874,11 +876,12 @@ fn compile_argument(c: &mut Compiler, tree: &Tree) -> CR {
|
|||
|
||||
fn compile_new_object_expression(c: &mut Compiler, t: TreeRef, tree: &Tree) -> CR {
|
||||
// We pass in the arguments.... by... field order?
|
||||
let Type::Object(ct, _) = c.semantics.type_of(t) else {
|
||||
let Type::Object(mid, ct, _) = c.semantics.type_of(t) else {
|
||||
c.push(inst_panic!("new obj not ob"));
|
||||
return OK;
|
||||
};
|
||||
let class = c.semantics.class_of(ct);
|
||||
|
||||
let class = c.semantics.class_of(mid, ct);
|
||||
|
||||
let field_list = tree.child_tree_of_kind(&c.syntax, TreeKind::FieldList)?;
|
||||
let mut field_bindings = HashMap::new();
|
||||
|
|
@ -951,12 +954,12 @@ fn compile_member_access(c: &mut Compiler, t: TreeRef, tree: &Tree) -> CR {
|
|||
let ident = tree.nth_token(2)?.as_str(&c.source);
|
||||
|
||||
let environment = match &typ {
|
||||
Type::Object(ct, _) => {
|
||||
let class = c.semantics.class_of(*ct);
|
||||
Type::Object(mid, ct, _) => {
|
||||
let class = c.semantics.class_of(*mid, *ct);
|
||||
class.env.clone()
|
||||
}
|
||||
Type::Class(ct, _) => {
|
||||
let class = c.semantics.class_of(*ct);
|
||||
Type::Class(mid, ct, _) => {
|
||||
let class = c.semantics.class_of(*mid, *ct);
|
||||
class.static_env.clone()
|
||||
}
|
||||
_ => {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use std::{collections::HashMap, fs, path::PathBuf, rc::Rc};
|
|||
|
||||
use compiler::compile;
|
||||
use parser::parse;
|
||||
use semantics::{check, Error, ImportRecord, Semantics};
|
||||
use semantics::{check, Error, ImportRecord, ModuleId, Semantics};
|
||||
use vm::{eval, Context};
|
||||
|
||||
pub mod compiler;
|
||||
|
|
@ -57,12 +57,12 @@ impl ModuleLoader for StandardModuleLoader {
|
|||
}
|
||||
|
||||
pub struct Module {
|
||||
id: u64,
|
||||
id: ModuleId,
|
||||
semantics: Rc<Semantics>,
|
||||
}
|
||||
|
||||
impl Module {
|
||||
pub fn id(&self) -> u64 {
|
||||
pub fn id(&self) -> ModuleId {
|
||||
self.id
|
||||
}
|
||||
|
||||
|
|
@ -103,10 +103,18 @@ impl Runtime {
|
|||
// TODO: Errors here are bad! Remember, run everything!
|
||||
match self.loader.load_module(&name)? {
|
||||
ModuleSource::SourceText(source) => {
|
||||
let mid = ModuleId::from(id_assign);
|
||||
id_assign += 1;
|
||||
|
||||
let source: Rc<str> = source.into();
|
||||
let (tree, lines) = parse(&source);
|
||||
let semantics =
|
||||
Rc::new(Semantics::new(name.clone().into(), source, tree, lines));
|
||||
let semantics = Rc::new(Semantics::new(
|
||||
mid,
|
||||
name.clone().into(),
|
||||
source,
|
||||
tree,
|
||||
lines,
|
||||
));
|
||||
|
||||
let mut normalized_imports = Vec::new();
|
||||
for import in semantics.imports() {
|
||||
|
|
@ -116,8 +124,7 @@ impl Runtime {
|
|||
normalized_imports.push((import, normalized));
|
||||
}
|
||||
|
||||
init_pending.insert(name, (id_assign, normalized_imports, semantics));
|
||||
id_assign += 1;
|
||||
init_pending.insert(name, (mid, normalized_imports, semantics));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,10 +116,19 @@ impl std::ops::Deref for ClassRef {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
pub struct ModuleId(u64);
|
||||
|
||||
impl From<u64> for ModuleId {
|
||||
fn from(value: u64) -> Self {
|
||||
ModuleId(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ImportRecord {
|
||||
pub name: String,
|
||||
pub module_id: u64,
|
||||
pub module_id: ModuleId,
|
||||
pub semantics: Weak<Semantics>,
|
||||
}
|
||||
|
||||
|
|
@ -164,12 +173,12 @@ pub enum Type {
|
|||
|
||||
// A class is the static type of a class; when the class is referred to
|
||||
// by name it has this type. (Distinct from an instance!)
|
||||
Class(TreeRef, Rc<str>),
|
||||
Class(ModuleId, TreeRef, Rc<str>),
|
||||
|
||||
// An object is the type of an allocated object instance. Details of its
|
||||
// class need to be fetched explicitly from the semantics via the
|
||||
// TreeRef and `Semantics::class_of`; they are computed lazily.
|
||||
Object(TreeRef, Rc<str>),
|
||||
Object(ModuleId, TreeRef, Rc<str>),
|
||||
|
||||
// An alternate is one or another type.
|
||||
Alternate(Box<[Type]>),
|
||||
|
|
@ -257,8 +266,8 @@ impl fmt::Display for Type {
|
|||
write!(f, "$_")
|
||||
}
|
||||
List(t) => write!(f, "list<{t}>"),
|
||||
Object(_, name) => write!(f, "{} instance", name),
|
||||
Class(_, name) => write!(f, "class {}", name),
|
||||
Object(_, _, name) => write!(f, "{} instance", name),
|
||||
Class(_, _, name) => write!(f, "class {}", name),
|
||||
Alternate(ts) => {
|
||||
let mut first = true;
|
||||
for t in ts.iter() {
|
||||
|
|
@ -318,8 +327,12 @@ impl std::cmp::Ord for Type {
|
|||
lv.cmp(&rv)
|
||||
}
|
||||
(Type::List(x), Type::List(y)) => x.cmp(y),
|
||||
(Type::Class(lt, _), Type::Class(rt, _)) => lt.index().cmp(&rt.index()),
|
||||
(Type::Object(lt, _), Type::Object(rt, _)) => lt.index().cmp(&rt.index()),
|
||||
(Type::Class(lm, lt, _), Type::Class(rm, rt, _)) => {
|
||||
(lm.0, lt.index()).cmp(&(rm.0, rt.index()))
|
||||
}
|
||||
(Type::Object(lm, lt, _), Type::Object(rm, rt, _)) => {
|
||||
(lm.0, lt.index()).cmp(&(rm.0, rt.index()))
|
||||
}
|
||||
(Type::Alternate(ll), Type::Alternate(rr)) => ll.cmp(rr),
|
||||
|
||||
_ => Ordering::Equal,
|
||||
|
|
@ -353,9 +366,11 @@ pub enum Declaration {
|
|||
declaration: TreeRef,
|
||||
location: Location,
|
||||
index: usize,
|
||||
exported: bool,
|
||||
},
|
||||
Function {
|
||||
declaration: TreeRef, //?
|
||||
exported: bool,
|
||||
},
|
||||
ExternFunction {
|
||||
declaration_type: Type,
|
||||
|
|
@ -363,10 +378,52 @@ pub enum Declaration {
|
|||
},
|
||||
Class {
|
||||
declaration: TreeRef, //?
|
||||
exported: bool,
|
||||
},
|
||||
Import {
|
||||
ImportedModule {
|
||||
declaration: TreeRef,
|
||||
exported: bool,
|
||||
},
|
||||
ImportedDeclaration {
|
||||
semantics: Weak<Semantics>,
|
||||
tree: Option<TreeRef>,
|
||||
declaration: Box<Declaration>,
|
||||
},
|
||||
}
|
||||
|
||||
impl Declaration {
|
||||
pub fn is_exported(&self) -> bool {
|
||||
match self {
|
||||
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> {
|
||||
match self {
|
||||
Declaration::Variable { declaration, .. } => Some(*declaration),
|
||||
Declaration::Function { declaration, .. } => Some(*declaration),
|
||||
Declaration::ExternFunction { .. } => None,
|
||||
Declaration::Class { declaration, .. } => Some(*declaration),
|
||||
Declaration::ImportedModule { declaration, .. } => Some(*declaration),
|
||||
Declaration::ImportedDeclaration { tree, .. } => *tree,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_exported(&mut self) {
|
||||
match self {
|
||||
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 {
|
||||
|
|
@ -426,6 +483,7 @@ impl Environment {
|
|||
declaration: t,
|
||||
location: self.location,
|
||||
index: self.next_index,
|
||||
exported: false,
|
||||
},
|
||||
);
|
||||
self.next_index += 1;
|
||||
|
|
@ -634,6 +692,7 @@ enum Incremental<T> {
|
|||
}
|
||||
|
||||
pub struct Semantics {
|
||||
mid: ModuleId,
|
||||
file: Rc<str>,
|
||||
source: Rc<str>,
|
||||
syntax_tree: Rc<SyntaxTree>,
|
||||
|
|
@ -654,7 +713,13 @@ pub struct Semantics {
|
|||
}
|
||||
|
||||
impl Semantics {
|
||||
pub fn new(file: Rc<str>, source: Rc<str>, tree: Rc<SyntaxTree>, lines: Rc<Lines>) -> Self {
|
||||
pub fn new(
|
||||
mid: ModuleId,
|
||||
file: Rc<str>,
|
||||
source: Rc<str>,
|
||||
tree: Rc<SyntaxTree>,
|
||||
lines: Rc<Lines>,
|
||||
) -> Self {
|
||||
let mut logical_parents = vec![None; tree.len()];
|
||||
if let Some(root) = tree.root() {
|
||||
set_logical_parents(&mut logical_parents, &tree, root, None);
|
||||
|
|
@ -663,6 +728,7 @@ impl Semantics {
|
|||
let root_environment = Environment::new(None, Location::Module);
|
||||
|
||||
let mut semantics = Semantics {
|
||||
mid,
|
||||
file,
|
||||
source,
|
||||
syntax_tree: tree.clone(),
|
||||
|
|
@ -842,7 +908,10 @@ impl Semantics {
|
|||
|
||||
let existing = environment.declarations.insert(
|
||||
name.as_str(&self.source).into(),
|
||||
Declaration::Function { declaration: *t },
|
||||
Declaration::Function {
|
||||
declaration: *t,
|
||||
exported: false,
|
||||
},
|
||||
);
|
||||
if existing.is_some() {
|
||||
self.report_error_tree(
|
||||
|
|
@ -865,49 +934,89 @@ impl Semantics {
|
|||
fn environment_of_file(&self, parent: EnvironmentRef, tree: &Tree) -> EnvironmentRef {
|
||||
let mut environment = Environment::new(Some(parent), Location::Module);
|
||||
|
||||
let mut explicit_exports = Vec::new();
|
||||
|
||||
for child in tree.children.iter() {
|
||||
let Child::Tree(t) = child else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let ct = &self.syntax_tree[*t];
|
||||
let binding = match ct.kind {
|
||||
let binding = {
|
||||
// Redeclare t to be mutable (and a copy)
|
||||
let mut t = *t;
|
||||
let mut exported = false;
|
||||
|
||||
// Loop here in order to dereference TreeKind::Export;
|
||||
// children of an export tree still go in the local
|
||||
// environment.
|
||||
loop {
|
||||
let ct = &self.syntax_tree[t];
|
||||
match ct.kind {
|
||||
TreeKind::FunctionDecl => {
|
||||
let Some(name) = ct.nth_token(1) else {
|
||||
continue;
|
||||
break None;
|
||||
};
|
||||
if name.kind != TokenKind::Identifier {
|
||||
continue;
|
||||
break None;
|
||||
}
|
||||
|
||||
let declaration = Declaration::Function { declaration: *t };
|
||||
Some(("function", name, declaration))
|
||||
let declaration = Declaration::Function {
|
||||
declaration: t,
|
||||
exported,
|
||||
};
|
||||
break Some(("function", name, declaration));
|
||||
}
|
||||
TreeKind::ClassDecl => {
|
||||
let Some(name) = ct.nth_token(1) else {
|
||||
continue;
|
||||
break None;
|
||||
};
|
||||
if name.kind != TokenKind::Identifier {
|
||||
continue;
|
||||
break None;
|
||||
}
|
||||
|
||||
let declaration = Declaration::Class { declaration: *t };
|
||||
Some(("class", name, declaration))
|
||||
let declaration = Declaration::Class {
|
||||
declaration: t,
|
||||
exported,
|
||||
};
|
||||
break Some(("class", name, declaration));
|
||||
}
|
||||
TreeKind::Import => {
|
||||
let Some(name) = ct.nth_token(3) else {
|
||||
continue;
|
||||
break None;
|
||||
};
|
||||
if name.kind != TokenKind::Identifier {
|
||||
break None;
|
||||
}
|
||||
|
||||
let declaration = Declaration::ImportedModule {
|
||||
declaration: t,
|
||||
exported,
|
||||
};
|
||||
break Some(("import", name, declaration));
|
||||
}
|
||||
TreeKind::Export => {
|
||||
let Some(inner) = ct.nth_tree(1) else {
|
||||
break None;
|
||||
};
|
||||
t = inner;
|
||||
exported = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
let declaration = Declaration::Import { declaration: *t };
|
||||
Some(("import", name, declaration))
|
||||
TreeKind::ExportList => {
|
||||
for child in &ct.children {
|
||||
if let Child::Token(tok) = child {
|
||||
if tok.kind == TokenKind::Identifier {
|
||||
explicit_exports.push(tok);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => break None,
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let ct = &self.syntax_tree[*t];
|
||||
if let Some((what, name, declaration)) = binding {
|
||||
let existing = environment
|
||||
.declarations
|
||||
|
|
@ -924,6 +1033,14 @@ impl Semantics {
|
|||
}
|
||||
}
|
||||
|
||||
for tok in explicit_exports {
|
||||
environment
|
||||
.declarations
|
||||
.get_mut(tok.as_str(&self.source))
|
||||
// NOTE: If not present, we report the error elsewhere.
|
||||
.map(|decl| decl.set_exported());
|
||||
}
|
||||
|
||||
EnvironmentRef::new(environment)
|
||||
}
|
||||
|
||||
|
|
@ -1113,7 +1230,23 @@ impl Semantics {
|
|||
EnvironmentRef::new(env)
|
||||
}
|
||||
|
||||
pub fn class_of(&self, t: TreeRef) -> ClassRef {
|
||||
pub fn class_of(&self, mid: ModuleId, t: TreeRef) -> ClassRef {
|
||||
if mid != self.mid {
|
||||
let weak_semantics = self
|
||||
.import_map
|
||||
.get()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.find(|(_, v)| v.module_id == mid)
|
||||
.unwrap()
|
||||
.1
|
||||
.semantics
|
||||
.clone();
|
||||
|
||||
let other_semantics = weak_semantics.upgrade().unwrap();
|
||||
return other_semantics.class_of(mid, t);
|
||||
}
|
||||
|
||||
{
|
||||
// I want to make sure that this borrow is dropped after this block.
|
||||
let mut borrow = self.classes.borrow_mut();
|
||||
|
|
@ -1194,6 +1327,7 @@ impl Semantics {
|
|||
index,
|
||||
declaration: field.declaration,
|
||||
location: Location::Slot,
|
||||
exported: false,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
@ -1203,6 +1337,7 @@ impl Semantics {
|
|||
(&*method.name).into(),
|
||||
Declaration::Function {
|
||||
declaration: method.declaration,
|
||||
exported: false,
|
||||
},
|
||||
)
|
||||
} else {
|
||||
|
|
@ -1210,6 +1345,7 @@ impl Semantics {
|
|||
(&*method.name).into(),
|
||||
Declaration::Function {
|
||||
declaration: method.declaration,
|
||||
exported: false,
|
||||
},
|
||||
)
|
||||
};
|
||||
|
|
@ -1281,12 +1417,12 @@ impl Semantics {
|
|||
.all(|(from, to)| self.can_convert(from, to))
|
||||
}
|
||||
|
||||
(Type::Object(c_from, _), Type::Object(c_to, _)) => {
|
||||
(Type::Object(m_from, c_from, _), Type::Object(m_to, c_to, _)) => {
|
||||
// TODO: Structural comparisons. All that matters is that
|
||||
// c_to has a subset of fields and methods, and the
|
||||
// fields and methods are all compatible.
|
||||
//
|
||||
c_from == c_to
|
||||
m_from == m_to && c_from == c_to
|
||||
}
|
||||
|
||||
// Avoid introducing more errors
|
||||
|
|
@ -1578,13 +1714,20 @@ impl Semantics {
|
|||
);
|
||||
return Some(Type::Error);
|
||||
}
|
||||
Declaration::Import { .. } => {
|
||||
Declaration::ImportedModule { .. } => {
|
||||
self.report_error_tree_ref(
|
||||
left_tree,
|
||||
"cannot assign a new value to an imported module",
|
||||
);
|
||||
return Some(Type::Error);
|
||||
}
|
||||
Declaration::ImportedDeclaration { .. } => {
|
||||
self.report_error_tree_ref(
|
||||
left_tree,
|
||||
"cannot assign a new value to a member of an imported module",
|
||||
);
|
||||
return Some(Type::Error);
|
||||
}
|
||||
}
|
||||
|
||||
let _ = environment;
|
||||
|
|
@ -1659,13 +1802,23 @@ impl Semantics {
|
|||
);
|
||||
Some(Type::Error)
|
||||
}
|
||||
Some(Declaration::Import { .. }) => {
|
||||
Some(Declaration::ImportedModule { .. }) => {
|
||||
self.report_error_tree(
|
||||
tree,
|
||||
format!("'{token}' is an imported module and cannot be used as a type"),
|
||||
);
|
||||
Some(Type::Error)
|
||||
}
|
||||
Some(Declaration::ImportedDeclaration {
|
||||
semantics,
|
||||
tree,
|
||||
declaration,
|
||||
}) => Some(
|
||||
semantics
|
||||
.upgrade()
|
||||
.unwrap()
|
||||
.type_of_declaration(*tree, declaration),
|
||||
),
|
||||
None => {
|
||||
if !environment.is_error {
|
||||
self.report_error_tree(tree, format!("Unrecognized type: '{token}'"));
|
||||
|
|
@ -1903,23 +2056,50 @@ impl Semantics {
|
|||
return Some(Type::Error);
|
||||
};
|
||||
|
||||
Some(self.type_of_declaration(t, declaration))
|
||||
Some(self.type_of_declaration(Some(t), declaration))
|
||||
}
|
||||
|
||||
pub fn member_environment(&self, t: TreeRef, typ: &Type) -> EnvironmentRef {
|
||||
match &typ {
|
||||
Type::Object(ct, _) => {
|
||||
let class = self.class_of(*ct);
|
||||
Type::Object(mid, ct, _) => {
|
||||
let class = self.class_of(*mid, *ct);
|
||||
class.env.clone()
|
||||
}
|
||||
Type::Class(ct, _) => {
|
||||
let class = self.class_of(*ct);
|
||||
Type::Class(mid, ct, _) => {
|
||||
let class = self.class_of(*mid, *ct);
|
||||
class.static_env.clone()
|
||||
}
|
||||
// Type::Module(_name) => {
|
||||
// // Woof. Would like to bind this now.
|
||||
// todo!();
|
||||
// }
|
||||
Type::Module(_, import) => {
|
||||
// TODO: Cache this somehow, man.
|
||||
let Some(other) = import.semantics.upgrade() else {
|
||||
self.internal_compiler_error(Some(t), "Unable to bind module");
|
||||
};
|
||||
|
||||
let Some(root) = other.syntax_tree.root() else {
|
||||
self.internal_compiler_error(Some(t), "Other syntax tree has no root");
|
||||
};
|
||||
let rt = &other.syntax_tree[root];
|
||||
assert_eq!(rt.kind, TreeKind::File);
|
||||
|
||||
let mut result = Environment::new(None, Location::Module);
|
||||
let other_env = other.environment_of(root);
|
||||
for (name, decl) in other_env.declarations.iter() {
|
||||
if decl.is_exported() {
|
||||
eprintln!("******* {} is exported!", name);
|
||||
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)
|
||||
}
|
||||
Type::Error => return Environment::error(),
|
||||
_ => {
|
||||
self.report_error_tree_ref(t, format!("cannot access members of '{typ}'"));
|
||||
|
|
@ -1957,7 +2137,7 @@ impl Semantics {
|
|||
let id = tree.nth_token(0)?.as_str(&self.source);
|
||||
let environment = self.environment_of(t);
|
||||
if let Some(declaration) = environment.bind(id) {
|
||||
return Some(self.type_of_declaration(t, declaration));
|
||||
return Some(self.type_of_declaration(Some(t), declaration));
|
||||
}
|
||||
|
||||
if !environment.is_error {
|
||||
|
|
@ -1966,18 +2146,26 @@ impl Semantics {
|
|||
Some(Type::Error)
|
||||
}
|
||||
|
||||
fn type_of_declaration(&self, t: TreeRef, declaration: &Declaration) -> Type {
|
||||
fn type_of_declaration(&self, t: Option<TreeRef>, declaration: &Declaration) -> Type {
|
||||
match declaration {
|
||||
Declaration::Variable { declaration, .. } => self.type_of(*declaration),
|
||||
Declaration::Function { declaration, .. } => self.type_of(*declaration),
|
||||
Declaration::Import { declaration, .. } => self.type_of(*declaration),
|
||||
Declaration::ImportedModule { declaration, .. } => self.type_of(*declaration),
|
||||
Declaration::ExternFunction {
|
||||
declaration_type, ..
|
||||
} => declaration_type.clone(),
|
||||
Declaration::Class { declaration, .. } => match self.type_of(*declaration) {
|
||||
Type::Object(cd, name) => Type::Class(cd, name.clone()),
|
||||
_ => self.internal_compiler_error(Some(t), "bound to a class not understood"),
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2126,7 +2314,7 @@ impl Semantics {
|
|||
// The details of a class are computed lazily, but this is enough of
|
||||
// a belly-button.
|
||||
let name = tree.nth_token(1)?;
|
||||
Some(Type::Object(t, name.as_str(&self.source).into()))
|
||||
Some(Type::Object(self.mid, t, name.as_str(&self.source).into()))
|
||||
}
|
||||
|
||||
fn type_of_field_decl(&self, tree: &Tree) -> Option<Type> {
|
||||
|
|
@ -2173,13 +2361,23 @@ impl Semantics {
|
|||
);
|
||||
Some(Type::Error)
|
||||
}
|
||||
Declaration::Import { .. } => {
|
||||
Declaration::ImportedModule { .. } => {
|
||||
self.report_error_tree(
|
||||
tree,
|
||||
format!("'{id}' is an imported module, and cannot be the value of a field"),
|
||||
);
|
||||
Some(Type::Error)
|
||||
}
|
||||
Declaration::ImportedDeclaration {
|
||||
semantics,
|
||||
tree,
|
||||
declaration,
|
||||
} => Some(
|
||||
semantics
|
||||
.upgrade()
|
||||
.unwrap()
|
||||
.type_of_declaration(*tree, declaration),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2427,7 +2625,7 @@ impl Semantics {
|
|||
Some(m) => {
|
||||
eprintln!("Import map:");
|
||||
for (k, b) in m.iter() {
|
||||
eprintln!(" {k} => {} ({})", b.name, b.module_id);
|
||||
eprintln!(" {k} => {} ({:?})", b.name, b.module_id);
|
||||
}
|
||||
eprintln!();
|
||||
}
|
||||
|
|
@ -2466,9 +2664,12 @@ impl Semantics {
|
|||
Declaration::Class { declaration, .. } => {
|
||||
eprintln!(" (class {declaration:?})");
|
||||
}
|
||||
Declaration::Import { declaration, .. } => {
|
||||
Declaration::ImportedModule { declaration, .. } => {
|
||||
eprintln!(" (imported module {declaration:?})");
|
||||
}
|
||||
Declaration::ImportedDeclaration { .. } => {
|
||||
eprintln!(" (imported member)");
|
||||
}
|
||||
};
|
||||
}
|
||||
environment = env.parent.clone();
|
||||
|
|
@ -2563,7 +2764,9 @@ pub fn check(s: &Semantics) {
|
|||
}
|
||||
|
||||
TreeKind::Export => {}
|
||||
TreeKind::ExportList => {}
|
||||
TreeKind::ExportList => {
|
||||
// TODO: Check that each name in the list is in the environment
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2686,8 +2889,9 @@ fn check_new_object_expression(s: &Semantics, tree: &Tree) {
|
|||
|
||||
let class_type = s.type_of(type_expression); // TODO: Should yield a ClassType not an ObjectType?
|
||||
match &class_type {
|
||||
Type::Object(c, _) => {
|
||||
let class = s.class_of(*c);
|
||||
Type::Object(mid, c, _) => {
|
||||
// Get the class def from ... place.
|
||||
let class = s.class_of(*mid, *c);
|
||||
|
||||
let mut any_errors = false;
|
||||
let mut field_bindings = HashMap::new();
|
||||
|
|
@ -2818,7 +3022,7 @@ mod tests {
|
|||
pub fn ice() {
|
||||
let source: Rc<str> = "1+1".into();
|
||||
let (tree, lines) = parse(&source);
|
||||
let semantics = Semantics::new("__test__".into(), source, tree.clone(), lines);
|
||||
let semantics = Semantics::new(ModuleId(0), "__test__".into(), source, tree.clone(), lines);
|
||||
semantics.internal_compiler_error(tree.root(), "oh no");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,5 +4,5 @@ fun test() -> string {
|
|||
foo.hello() + " world"
|
||||
}
|
||||
|
||||
// @ignore WIP
|
||||
// TODO: Obviously run the code duh
|
||||
// @no-errors
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue