[fine] Tokens are by reference, ephemera
It's another jump, perhaps, but smaller arrays, and now we can track ephemera efficiently without bloating child trees. (We could also put ephemera inline with the child trees but then nth_token would be unwieldy, and it would lower our data density.)
This commit is contained in:
parent
a5173be680
commit
0b0b5d72d0
3 changed files with 298 additions and 105 deletions
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{
|
||||
parser::{Child, SyntaxTree, Tree, TreeKind, TreeRef},
|
||||
parser::{Child, SyntaxTree, TokenRef, Tree, TreeKind, TreeRef},
|
||||
tokens::{Lines, Token, TokenKind},
|
||||
vm::StackValue,
|
||||
};
|
||||
|
|
@ -712,6 +712,42 @@ pub struct Semantics {
|
|||
classes: RefCell<Vec<Incremental<ClassRef>>>,
|
||||
}
|
||||
|
||||
impl std::ops::Index<TreeRef> for Semantics {
|
||||
type Output = Tree;
|
||||
|
||||
#[inline]
|
||||
fn index(&self, index: TreeRef) -> &Self::Output {
|
||||
&self.syntax_tree[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Index<&TreeRef> for Semantics {
|
||||
type Output = Tree;
|
||||
|
||||
#[inline]
|
||||
fn index(&self, index: &TreeRef) -> &Self::Output {
|
||||
&self.syntax_tree[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Index<TokenRef> for Semantics {
|
||||
type Output = Token;
|
||||
|
||||
#[inline]
|
||||
fn index(&self, index: TokenRef) -> &Self::Output {
|
||||
&self.syntax_tree[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Index<&TokenRef> for Semantics {
|
||||
type Output = Token;
|
||||
|
||||
#[inline]
|
||||
fn index(&self, index: &TokenRef) -> &Self::Output {
|
||||
&self.syntax_tree[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl Semantics {
|
||||
pub fn new(
|
||||
mid: ModuleId,
|
||||
|
|
@ -801,10 +837,10 @@ impl Semantics {
|
|||
self.syntax_tree
|
||||
.root()
|
||||
.map(|file| {
|
||||
self.syntax_tree[file]
|
||||
self[file]
|
||||
.children_of_kind(&self.syntax_tree, TreeKind::Import)
|
||||
.filter_map(|import| {
|
||||
let tok = self.syntax_tree[import].nth_token(1)?;
|
||||
let tok = &self[self[import].nth_token(1)?];
|
||||
if tok.kind != TokenKind::String {
|
||||
None
|
||||
} else {
|
||||
|
|
@ -862,17 +898,18 @@ impl Semantics {
|
|||
where
|
||||
T: ToString,
|
||||
{
|
||||
let tree = &self.syntax_tree[tree];
|
||||
let tree = &self[tree];
|
||||
self.report_error_span(tree.start_pos, tree.end_pos, error)
|
||||
}
|
||||
|
||||
fn gather_errors(&mut self, tree: TreeRef) {
|
||||
let mut stack = vec![tree];
|
||||
while let Some(tr) = stack.pop() {
|
||||
let tree = &self.syntax_tree[tr];
|
||||
let tree = &self[tr];
|
||||
for child in &tree.children {
|
||||
match child {
|
||||
Child::Token(t) => {
|
||||
let t = &self[*t];
|
||||
if t.kind == TokenKind::Error {
|
||||
self.report_error_span(t.start(), t.end(), t.as_str(&self.source));
|
||||
}
|
||||
|
|
@ -970,7 +1007,7 @@ impl Semantics {
|
|||
*state = Incremental::InProgress;
|
||||
}
|
||||
|
||||
let tree = &self.syntax_tree[t];
|
||||
let tree = &self[t];
|
||||
// eprintln!(">>> environment_of => {tree:?}");
|
||||
|
||||
let parent = match self.logical_parents[t.index()] {
|
||||
|
|
@ -1000,14 +1037,14 @@ impl Semantics {
|
|||
for child in tree.children.iter() {
|
||||
match child {
|
||||
Child::Tree(t) => {
|
||||
let ct = &self.syntax_tree[*t];
|
||||
let ct = &self[*t];
|
||||
if ct.kind == TreeKind::FunctionDecl {
|
||||
let Some(name) = ct.nth_token(1) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let existing = environment.declarations.insert(
|
||||
name.as_str(&self.source).into(),
|
||||
self[name].as_str(&self.source).into(),
|
||||
Declaration {
|
||||
location: Location::Function,
|
||||
index: self.function_index_of(*t),
|
||||
|
|
@ -1021,7 +1058,7 @@ impl Semantics {
|
|||
ct,
|
||||
format!(
|
||||
"duplicate definition of function '{}'",
|
||||
name.as_str(&self.source)
|
||||
self[name].as_str(&self.source)
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
@ -1053,12 +1090,13 @@ impl Semantics {
|
|||
// children of an export tree still go in the local
|
||||
// environment.
|
||||
loop {
|
||||
let ct = &self.syntax_tree[t];
|
||||
let ct = &self[t];
|
||||
match ct.kind {
|
||||
TreeKind::FunctionDecl => {
|
||||
let Some(name) = ct.nth_token(1) else {
|
||||
break None;
|
||||
};
|
||||
let name = &self[name];
|
||||
if name.kind != TokenKind::Identifier {
|
||||
break None;
|
||||
}
|
||||
|
|
@ -1076,6 +1114,7 @@ impl Semantics {
|
|||
let Some(name) = ct.nth_token(1) else {
|
||||
break None;
|
||||
};
|
||||
let name = &self[name];
|
||||
if name.kind != TokenKind::Identifier {
|
||||
break None;
|
||||
}
|
||||
|
|
@ -1093,6 +1132,7 @@ impl Semantics {
|
|||
let Some(name) = ct.nth_token(3) else {
|
||||
break None;
|
||||
};
|
||||
let name = &self[name];
|
||||
if name.kind != TokenKind::Identifier {
|
||||
break None;
|
||||
}
|
||||
|
|
@ -1117,6 +1157,7 @@ impl Semantics {
|
|||
TreeKind::ExportList => {
|
||||
for child in &ct.children {
|
||||
if let Child::Token(tok) = child {
|
||||
let tok = &self[tok];
|
||||
if tok.kind == TokenKind::Identifier {
|
||||
explicit_exports.push(tok);
|
||||
}
|
||||
|
|
@ -1128,7 +1169,7 @@ impl Semantics {
|
|||
}
|
||||
};
|
||||
|
||||
let ct = &self.syntax_tree[*t];
|
||||
let ct = &self[*t];
|
||||
if let Some((what, name, declaration)) = binding {
|
||||
let existing = environment
|
||||
.declarations
|
||||
|
|
@ -1180,7 +1221,7 @@ impl Semantics {
|
|||
};
|
||||
|
||||
let mut environment = Environment::new(self.mid, Some(parent), location);
|
||||
environment.insert(name.as_str(&self.source), declaration);
|
||||
environment.insert(self[name].as_str(&self.source), declaration);
|
||||
|
||||
EnvironmentRef::new(environment)
|
||||
}
|
||||
|
|
@ -1193,10 +1234,10 @@ impl Semantics {
|
|||
let Child::Tree(ct) = child else {
|
||||
continue;
|
||||
};
|
||||
let param = &self.syntax_tree[*ct];
|
||||
let param = &self[*ct];
|
||||
match param.kind {
|
||||
TreeKind::SelfParameter => {
|
||||
let param_name = param.nth_token(0).unwrap();
|
||||
let param_name = &self[param.nth_token(0).unwrap()];
|
||||
if environment
|
||||
.insert(param_name.as_str(&self.source), *ct)
|
||||
.is_some()
|
||||
|
|
@ -1216,6 +1257,7 @@ impl Semantics {
|
|||
let Some(param_name) = param.nth_token(0) else {
|
||||
continue;
|
||||
};
|
||||
let param_name = &self[param_name];
|
||||
|
||||
let param_str = param_name.as_str(&self.source);
|
||||
if environment.insert(param_str, *ct).is_some() {
|
||||
|
|
@ -1237,13 +1279,13 @@ impl Semantics {
|
|||
return parent;
|
||||
};
|
||||
|
||||
let iterator = &self.syntax_tree[it];
|
||||
let iterator = &self[it];
|
||||
let Some(id) = iterator.nth_token(0) else {
|
||||
return parent;
|
||||
};
|
||||
|
||||
let mut environment = Environment::new(self.mid, Some(parent), Location::Local);
|
||||
environment.insert(id.as_str(&self.source), it);
|
||||
environment.insert(&self[id].as_str(&self.source), it);
|
||||
EnvironmentRef::new(environment)
|
||||
}
|
||||
|
||||
|
|
@ -1284,14 +1326,14 @@ impl Semantics {
|
|||
let Some(match_body) = tree.parent else {
|
||||
self.internal_compiler_error(Some(t), "no parent on match arm");
|
||||
};
|
||||
let match_body = &self.syntax_tree[match_body];
|
||||
let match_body = &self[match_body];
|
||||
if match_body.kind != TreeKind::MatchBody {
|
||||
self.internal_compiler_error(Some(t), "match arm parent not match body");
|
||||
}
|
||||
let Some(match_expression) = match_body.parent else {
|
||||
self.internal_compiler_error(Some(t), "no parent on match body");
|
||||
};
|
||||
let match_expression = &self.syntax_tree[match_expression];
|
||||
let match_expression = &self[match_expression];
|
||||
if match_expression.kind != TreeKind::MatchExpression {
|
||||
self.internal_compiler_error(Some(t), "match body parent not match expression");
|
||||
}
|
||||
|
|
@ -1343,7 +1385,7 @@ impl Semantics {
|
|||
// TODO: This binding should be un-assignable! Don't assign to this!
|
||||
|
||||
let mut env = Environment::new(self.mid, Some(parent), Location::Local);
|
||||
env.insert(variable.as_str(&self.source), variable_decl);
|
||||
env.insert(&self[variable].as_str(&self.source), variable_decl);
|
||||
EnvironmentRef::new(env)
|
||||
}
|
||||
|
||||
|
|
@ -1371,25 +1413,25 @@ impl Semantics {
|
|||
}
|
||||
|
||||
// TODO: Right now there's only one way to make a class decl. :P
|
||||
let tree = &self.syntax_tree[t];
|
||||
let tree = &self[t];
|
||||
assert_eq!(tree.kind, TreeKind::ClassDecl);
|
||||
|
||||
let name = tree
|
||||
.nth_token(1)
|
||||
.map(|t| t.as_str(&self.source))
|
||||
.map(|t| self[t].as_str(&self.source))
|
||||
.unwrap_or("<??>");
|
||||
|
||||
// Fields
|
||||
let mut fields = Vec::new();
|
||||
for field in tree.children_of_kind(&self.syntax_tree, TreeKind::FieldDecl) {
|
||||
let f = &self.syntax_tree[field];
|
||||
let f = &self[field];
|
||||
if let Some(field_name) = f.nth_token(0) {
|
||||
let field_type = f
|
||||
.nth_tree(2)
|
||||
.map(|t| self.type_of(t))
|
||||
.unwrap_or_else(|| self.type_error_for(f));
|
||||
fields.push(FieldDecl {
|
||||
name: field_name.as_str(&self.source).into(),
|
||||
name: self[field_name].as_str(&self.source).into(),
|
||||
declaration: field,
|
||||
field_type,
|
||||
});
|
||||
|
|
@ -1399,8 +1441,10 @@ impl Semantics {
|
|||
// Methods
|
||||
let mut methods = Vec::new();
|
||||
for method in tree.children_of_kind(&self.syntax_tree, TreeKind::FunctionDecl) {
|
||||
let m = &self.syntax_tree[method];
|
||||
let m = &self[method];
|
||||
if let Some(method_name) = m.nth_token(1) {
|
||||
let method_name = &self[method_name];
|
||||
|
||||
// TODO: Check to see if it is actually a method, or if it is a static function.
|
||||
let decl_type = self.type_of(method);
|
||||
match decl_type {
|
||||
|
|
@ -1582,7 +1626,7 @@ impl Semantics {
|
|||
*state = Incremental::InProgress;
|
||||
}
|
||||
|
||||
let tree = &self.syntax_tree[t];
|
||||
let tree = &self[t];
|
||||
// eprintln!(">>> type_of => {tree:?}");
|
||||
|
||||
let result = match tree.kind {
|
||||
|
|
@ -1641,7 +1685,7 @@ impl Semantics {
|
|||
fn type_of_unary(&self, tree: &Tree) -> Option<Type> {
|
||||
assert_eq!(tree.kind, TreeKind::UnaryExpression);
|
||||
|
||||
let op = tree.nth_token(0)?;
|
||||
let op = &self[tree.nth_token(0)?];
|
||||
let expr = tree.nth_tree(1)?;
|
||||
|
||||
let argument_type = self.type_of(expr);
|
||||
|
|
@ -1682,7 +1726,7 @@ impl Semantics {
|
|||
assert_eq!(tree.kind, TreeKind::BinaryExpression);
|
||||
let left_tree = tree.nth_tree(0)?;
|
||||
let lhs = self.type_of(left_tree);
|
||||
let op = tree.nth_token(1)?;
|
||||
let op = &self[tree.nth_token(1)?];
|
||||
let rhs = self.type_of(tree.nth_tree(2)?);
|
||||
|
||||
match (op.kind, lhs, rhs) {
|
||||
|
|
@ -1740,7 +1784,7 @@ impl Semantics {
|
|||
(_, _, Type::Error(e)) => Some(Type::Error(e)),
|
||||
|
||||
// Assignments are fun.
|
||||
(TokenKind::Equal, a, b) => self.type_of_assignment(left_tree, a, b, op),
|
||||
(TokenKind::Equal, a, b) => self.type_of_assignment(left_tree, a, b, &op),
|
||||
|
||||
// Missed the whole table, it must be an error.
|
||||
(_, left_type, right_type) => {
|
||||
|
|
@ -1765,7 +1809,7 @@ impl Semantics {
|
|||
op: &Token,
|
||||
) -> Option<Type> {
|
||||
// Ensure the left tree is an lvalue
|
||||
let tree = &self.syntax_tree[left_tree];
|
||||
let tree = &self[left_tree];
|
||||
|
||||
#[allow(unused_assignments)]
|
||||
let mut environment = None;
|
||||
|
|
@ -1773,7 +1817,7 @@ impl Semantics {
|
|||
let declaration = match tree.kind {
|
||||
// TODO: Assign to list access
|
||||
TreeKind::Identifier => {
|
||||
let id = tree.nth_token(0)?.as_str(&self.source);
|
||||
let id = self[tree.nth_token(0)?].as_str(&self.source);
|
||||
environment = Some(self.environment_of(left_tree));
|
||||
match environment.as_ref().unwrap().bind(id) {
|
||||
Some(decl) => decl,
|
||||
|
|
@ -1788,7 +1832,7 @@ impl Semantics {
|
|||
}
|
||||
}
|
||||
TreeKind::MemberAccess => {
|
||||
let id = tree.nth_token(2)?.as_str(&self.source);
|
||||
let id = self[tree.nth_token(2)?].as_str(&self.source);
|
||||
let typ = self.type_of(tree.nth_tree(0)?);
|
||||
environment = Some(self.member_environment(left_tree, &typ));
|
||||
match environment.as_ref().unwrap().bind(id) {
|
||||
|
|
@ -1873,7 +1917,7 @@ impl Semantics {
|
|||
assert_eq!(tree.kind, TreeKind::TypeIdentifier);
|
||||
|
||||
// TODO: This will *clearly* need to get better.
|
||||
let token = tree.nth_token(0)?.as_str(&self.source);
|
||||
let token = self[tree.nth_token(0)?].as_str(&self.source);
|
||||
match token {
|
||||
"f64" => Some(Type::F64),
|
||||
"string" => Some(Type::String),
|
||||
|
|
@ -1989,7 +2033,7 @@ impl Semantics {
|
|||
fn type_of_literal(&self, tree: &Tree) -> Option<Type> {
|
||||
assert_eq!(tree.kind, TreeKind::LiteralExpression);
|
||||
|
||||
let tok = tree.nth_token(0)?;
|
||||
let tok = &self[tree.nth_token(0)?];
|
||||
let pig = match tok.kind {
|
||||
TokenKind::Number => Type::F64,
|
||||
TokenKind::String => Type::String,
|
||||
|
|
@ -2015,7 +2059,7 @@ impl Semantics {
|
|||
|
||||
let has_else = tree
|
||||
.nth_token(3)
|
||||
.map(|t| t.kind == TokenKind::Else)
|
||||
.map(|t| self[t].kind == TokenKind::Else)
|
||||
.unwrap_or(false);
|
||||
let else_type = if has_else {
|
||||
Some(self.type_of(tree.nth_tree(4)?))
|
||||
|
|
@ -2052,7 +2096,7 @@ impl Semantics {
|
|||
let f_ref = tree.nth_tree(0)?;
|
||||
let f = self.type_of(f_ref);
|
||||
|
||||
let arg_list = &self.syntax_tree[tree.nth_tree(1)?];
|
||||
let arg_list = &self[tree.nth_tree(1)?];
|
||||
let arg_types: Vec<_> = arg_list
|
||||
.children
|
||||
.iter()
|
||||
|
|
@ -2161,7 +2205,7 @@ impl Semantics {
|
|||
let lhs = tree.nth_tree(0)?;
|
||||
let typ = self.type_of(lhs);
|
||||
let env = self.member_environment(lhs, &typ);
|
||||
let id = tree.nth_token(2)?;
|
||||
let id = &self[tree.nth_token(2)?];
|
||||
if id.kind != TokenKind::Identifier {
|
||||
return Some(self.type_error_for(tree));
|
||||
}
|
||||
|
|
@ -2202,7 +2246,7 @@ impl Semantics {
|
|||
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];
|
||||
let rt = &other[root];
|
||||
assert_eq!(rt.kind, TreeKind::File);
|
||||
|
||||
let mut result = Environment::new(self.mid, None, Location::Module);
|
||||
|
|
@ -2227,7 +2271,7 @@ impl Semantics {
|
|||
assert_eq!(tree.kind, TreeKind::ExpressionStatement);
|
||||
let last_is_semicolon = tree
|
||||
.nth_token(tree.children.len() - 1)
|
||||
.map(|t| t.kind == TokenKind::Semicolon)
|
||||
.map(|t| self[t].kind == TokenKind::Semicolon)
|
||||
.unwrap_or(false);
|
||||
|
||||
let expression_type = tree.nth_tree(0).map(|t| self.type_of(t));
|
||||
|
|
@ -2249,7 +2293,7 @@ impl Semantics {
|
|||
fn type_of_identifier(&self, t: TreeRef, tree: &Tree) -> Option<Type> {
|
||||
assert_eq!(tree.kind, TreeKind::Identifier);
|
||||
|
||||
let id = tree.nth_token(0)?.as_str(&self.source);
|
||||
let id = self[tree.nth_token(0)?].as_str(&self.source);
|
||||
let environment = self.environment_of(t);
|
||||
if let Some(declaration) = environment.bind(id) {
|
||||
let typ = self.type_of_declaration(declaration);
|
||||
|
|
@ -2303,13 +2347,13 @@ impl Semantics {
|
|||
|
||||
fn type_of_self_parameter(&self, tree: &Tree) -> Option<Type> {
|
||||
let pl = tree.parent?;
|
||||
let param_list = &self.syntax_tree[pl];
|
||||
let param_list = &self[pl];
|
||||
|
||||
let fd = param_list.parent?;
|
||||
let function_decl = &self.syntax_tree[fd];
|
||||
let function_decl = &self[fd];
|
||||
|
||||
let cd = function_decl.parent?;
|
||||
let class_decl = &self.syntax_tree[cd];
|
||||
let class_decl = &self[cd];
|
||||
|
||||
if class_decl.kind != TreeKind::ClassDecl {
|
||||
let error = self.report_error_tree(tree, "self parameter only allowed in methods");
|
||||
|
|
@ -2322,7 +2366,7 @@ impl Semantics {
|
|||
fn type_of_self_reference(&self, t: TreeRef, tree: &Tree) -> Option<Type> {
|
||||
assert_eq!(tree.kind, TreeKind::SelfReference);
|
||||
|
||||
let id = tree.nth_token(0)?.as_str(&self.source);
|
||||
let id = self[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(declaration));
|
||||
|
|
@ -2349,7 +2393,7 @@ impl Semantics {
|
|||
let mut parameter_types = Vec::new();
|
||||
for p in param_list.child_trees() {
|
||||
let p_type = Box::new(self.type_of(p));
|
||||
if self.syntax_tree[p].kind == TreeKind::SelfParameter {
|
||||
if self[p].kind == TreeKind::SelfParameter {
|
||||
self_type = Some(p_type);
|
||||
} else {
|
||||
parameter_types.push(p_type);
|
||||
|
|
@ -2382,7 +2426,7 @@ impl Semantics {
|
|||
|
||||
fn type_of_iterator_variable(&self, tree: &Tree) -> Option<Type> {
|
||||
assert_eq!(tree.kind, TreeKind::IteratorVariable);
|
||||
let parent = &self.syntax_tree[tree.parent?];
|
||||
let parent = &self[tree.parent?];
|
||||
assert_eq!(parent.kind, TreeKind::ForStatement);
|
||||
|
||||
let enumerable = parent.nth_tree(3)?;
|
||||
|
|
@ -2443,7 +2487,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)?;
|
||||
let name = &self[tree.nth_token(1)?];
|
||||
|
||||
// NOTE: There's a kind of a weird design decision here, which is to
|
||||
// return an instance type instead of a class type. This is
|
||||
|
|
@ -2478,7 +2522,7 @@ impl Semantics {
|
|||
assert_eq!(tree.kind, TreeKind::FieldValue);
|
||||
|
||||
if let Some(colon) = tree.nth_token(1) {
|
||||
if colon.kind == TokenKind::Colon {
|
||||
if self[colon].kind == TokenKind::Colon {
|
||||
// Form 1: { x: e, ... }
|
||||
return Some(self.type_of(tree.nth_tree(2)?));
|
||||
}
|
||||
|
|
@ -2486,7 +2530,7 @@ impl Semantics {
|
|||
|
||||
// Form 2: { x, ... }
|
||||
let environment = self.environment_of(t);
|
||||
let id = tree.nth_token(0)?.as_str(&self.source);
|
||||
let id = self[tree.nth_token(0)?].as_str(&self.source);
|
||||
let declaration = match environment.bind(id) {
|
||||
Some(d) => d,
|
||||
None => {
|
||||
|
|
@ -2593,7 +2637,7 @@ impl Semantics {
|
|||
}
|
||||
|
||||
fn type_of_import(&self, tree: &Tree) -> Option<Type> {
|
||||
let tok = tree.nth_token(1)?;
|
||||
let tok = &self[tree.nth_token(1)?];
|
||||
if tok.kind != TokenKind::String {
|
||||
return Some(self.type_error_for(tree));
|
||||
}
|
||||
|
|
@ -2618,10 +2662,10 @@ impl Semantics {
|
|||
fn constant_eval(&self, t: TreeRef) -> Option<StackValue> {
|
||||
// TODO: Make this cached, incremental, so the compiler can use it for optimizations.
|
||||
|
||||
let tree = &self.syntax_tree[t];
|
||||
let tree = &self[t];
|
||||
match tree.kind {
|
||||
TreeKind::LiteralExpression => {
|
||||
let tok = tree.nth_token(0)?;
|
||||
let tok = &self[tree.nth_token(0)?];
|
||||
match self.type_of(t) {
|
||||
Type::F64 => Some(StackValue::Float(tok.as_str(&self.source).parse().unwrap())),
|
||||
Type::Bool => Some(StackValue::Bool(tok.kind == TokenKind::True)),
|
||||
|
|
@ -2635,7 +2679,7 @@ impl Semantics {
|
|||
|
||||
TreeKind::IsExpression => {
|
||||
let pt = tree.nth_tree(2)?;
|
||||
let pattern = &self.syntax_tree[pt];
|
||||
let pattern = &self[pt];
|
||||
if pattern
|
||||
.child_of_kind(&self.syntax_tree, TreeKind::WildcardPattern)
|
||||
.is_some()
|
||||
|
|
@ -2651,7 +2695,7 @@ impl Semantics {
|
|||
TreeKind::GroupingExpression => self.constant_eval(tree.nth_tree(1)?),
|
||||
|
||||
TreeKind::UnaryExpression => {
|
||||
let op = tree.nth_token(0)?.kind;
|
||||
let op = self[tree.nth_token(0)?].kind;
|
||||
let val = self.constant_eval(tree.nth_tree(1)?)?;
|
||||
|
||||
match (op, val) {
|
||||
|
|
@ -2665,7 +2709,7 @@ impl Semantics {
|
|||
TreeKind::BinaryExpression => {
|
||||
let left = self.constant_eval(tree.nth_tree(0)?)?;
|
||||
let right = self.constant_eval(tree.nth_tree(2)?)?;
|
||||
let op = tree.nth_token(1)?.kind;
|
||||
let op = self[tree.nth_token(1)?].kind;
|
||||
match (op, left, right) {
|
||||
(TokenKind::Plus, StackValue::Float(a), StackValue::Float(b)) => {
|
||||
Some(StackValue::Float(a + b))
|
||||
|
|
@ -2787,11 +2831,11 @@ impl Semantics {
|
|||
}
|
||||
|
||||
if let Some(tr) = tr {
|
||||
eprintln!("This is about the tree: {:?}", &self.syntax_tree[tr]);
|
||||
eprintln!("This is about the tree: {:?}", &self[tr]);
|
||||
eprintln!("The logical parent chain of the tree was:\n");
|
||||
let mut current = Some(tr);
|
||||
while let Some(c) = current {
|
||||
let t = &self.syntax_tree[c];
|
||||
let t = &self[c];
|
||||
eprintln!(" {:?} [{}-{})", t.kind, t.start_pos, t.end_pos);
|
||||
current = self.logical_parents[c.index()];
|
||||
}
|
||||
|
|
@ -2824,7 +2868,7 @@ impl Semantics {
|
|||
|
||||
pub fn check(s: &Semantics) {
|
||||
for t in s.syntax_tree.trees() {
|
||||
let tree = &s.syntax_tree[t];
|
||||
let tree = &s[t];
|
||||
match tree.kind {
|
||||
TreeKind::Error => {} // already reported
|
||||
TreeKind::File => {}
|
||||
|
|
@ -2938,7 +2982,7 @@ fn check_function_decl(s: &Semantics, t: TreeRef, tree: &Tree) {
|
|||
// Just work very hard to get an appropriate error span.
|
||||
let (start, end) = return_type_tree
|
||||
.map(|t| {
|
||||
let rtt = &s.syntax_tree[t];
|
||||
let rtt = &s[t];
|
||||
(rtt.start_pos, rtt.end_pos)
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
|
|
@ -2946,7 +2990,7 @@ fn check_function_decl(s: &Semantics, t: TreeRef, tree: &Tree) {
|
|||
let end_tok = tree
|
||||
.nth_token(1)
|
||||
.unwrap_or_else(|| tree.nth_token(0).unwrap());
|
||||
(start, end_tok.end())
|
||||
(start, s[end_tok].end())
|
||||
});
|
||||
|
||||
s.report_error_span(start, end, format!("the body of this function yields a value of type '{body_type}', but callers expect this function to produce a '{return_type}'"));
|
||||
|
|
@ -2958,6 +3002,7 @@ fn check_let(s: &Semantics, tree: &Tree) {
|
|||
let Some(name) = tree.nth_token(1) else {
|
||||
return;
|
||||
};
|
||||
let name = &s[name];
|
||||
let Some(expr) = tree.nth_tree(3) else { return };
|
||||
|
||||
if let Type::Method(..) = s.type_of(expr) {
|
||||
|
|
@ -2974,7 +3019,7 @@ fn check_return_statement(s: &Semantics, tree: &Tree) {
|
|||
|
||||
let mut enclosing_function = tree.parent;
|
||||
while let Some(fp) = enclosing_function {
|
||||
let fpt = &s.syntax_tree[fp];
|
||||
let fpt = &s[fp];
|
||||
if fpt.kind == TreeKind::FunctionDecl {
|
||||
break;
|
||||
}
|
||||
|
|
@ -3033,10 +3078,10 @@ fn check_new_object_expression(s: &Semantics, tree: &Tree) {
|
|||
let mut any_errors = false;
|
||||
let mut field_bindings = HashMap::new();
|
||||
for field in field_list.children_of_kind(&s.syntax_tree, TreeKind::FieldValue) {
|
||||
let f = &s.syntax_tree[field];
|
||||
let f = &s[field];
|
||||
if let Some(name) = f.nth_token(0) {
|
||||
let field_type = s.type_of(field);
|
||||
field_bindings.insert(name.as_str(&s.source), (field, field_type));
|
||||
field_bindings.insert(s[name].as_str(&s.source), (field, field_type));
|
||||
} else {
|
||||
any_errors = true;
|
||||
}
|
||||
|
|
@ -3085,11 +3130,11 @@ fn check_new_object_expression(s: &Semantics, tree: &Tree) {
|
|||
fn check_class_declaration(s: &Semantics, tree: &Tree) {
|
||||
let mut fields = HashMap::new();
|
||||
for field in tree.children_of_kind(&s.syntax_tree, TreeKind::FieldDecl) {
|
||||
let f = &s.syntax_tree[field];
|
||||
let f = &s[field];
|
||||
let Some(name) = f.nth_token(0) else {
|
||||
continue;
|
||||
};
|
||||
let name = name.as_str(&s.source);
|
||||
let name = s[name].as_str(&s.source);
|
||||
match fields.insert(name, field) {
|
||||
Some(_) => {
|
||||
s.report_error_tree(f, format!("duplicate definition of field '{name}'"));
|
||||
|
|
@ -3102,7 +3147,7 @@ fn check_class_declaration(s: &Semantics, tree: &Tree) {
|
|||
fn check_pattern(s: &Semantics, tree: &Tree) {
|
||||
// If there's an AND then it must produce a boolean.
|
||||
let and_index = tree.children.iter().position(|c| match c {
|
||||
Child::Token(t) => t.kind == TokenKind::And,
|
||||
Child::Token(t) => s[t].kind == TokenKind::And,
|
||||
_ => false,
|
||||
});
|
||||
if let Some(and_index) = and_index {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue