fixing scoping bug
This commit is contained in:
parent
24a3aed360
commit
784d552c1d
|
@ -225,6 +225,7 @@ Struct := struct {
|
|||
$new := fn(a: uint, b: uint): Self return .(a, b)
|
||||
|
||||
$swap := fn(s: ^Self): void {
|
||||
_ = diff(*s)
|
||||
t := s.a
|
||||
s.a = s.b
|
||||
s.b = t
|
||||
|
|
|
@ -35,7 +35,7 @@ pub use fs::*;
|
|||
pub use utils::Ent;
|
||||
use {
|
||||
self::{
|
||||
parser::{ExprRef, Pos},
|
||||
parser::{CommentOr, Expr, ExprRef, Pos},
|
||||
ty::{ArrayLen, Builtin, Module},
|
||||
utils::EntVec,
|
||||
},
|
||||
|
@ -1262,6 +1262,28 @@ impl Types {
|
|||
|
||||
debug_assert_eq!(self.tasks.len(), 0);
|
||||
}
|
||||
|
||||
fn scope_of<'a>(&self, parent: ty::Id, file: &'a parser::Ast) -> Option<&'a [Expr<'a>]> {
|
||||
match parent.expand() {
|
||||
ty::Kind::Struct(s) => {
|
||||
if let Expr::Struct { fields: [.., CommentOr::Or(Err(scope))], .. } =
|
||||
self.ins.structs[s].ast.get(file)
|
||||
{
|
||||
Some(scope)
|
||||
} else {
|
||||
Some(&[])
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn parent_of(&self, ty: ty::Id) -> Option<ty::Id> {
|
||||
match ty.expand() {
|
||||
ty::Kind::Struct(s) => Some(self.ins.structs[s].file.into()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct OptLayout {
|
||||
|
|
114
lang/src/son.rs
114
lang/src/son.rs
|
@ -27,7 +27,7 @@ use {
|
|||
},
|
||||
hashbrown::hash_map,
|
||||
hbbytecode::DisasmError,
|
||||
std::intrinsics::vtable_size,
|
||||
std::panic,
|
||||
};
|
||||
|
||||
const VOID: Nid = 0;
|
||||
|
@ -2572,7 +2572,7 @@ impl<'a> Codegen<'a> {
|
|||
}
|
||||
|
||||
pub fn generate(&mut self, entry: Module) {
|
||||
self.find_type(0, entry, entry, Err("main"));
|
||||
self.find_type_in_file(0, entry, Err("main"));
|
||||
if self.tys.ins.funcs.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
@ -2820,7 +2820,7 @@ impl<'a> Codegen<'a> {
|
|||
Some(Value::var(index).ty(var.ty))
|
||||
}
|
||||
Expr::Ident { id, pos, .. } => {
|
||||
let decl = self.find_type(pos, self.ci.file, self.ci.file, Ok(id));
|
||||
let decl = self.find_type_in_scope(pos, Ok(id));
|
||||
match decl.expand() {
|
||||
ty::Kind::NEVER => Value::NEVER,
|
||||
ty::Kind::Global(global) => self.gen_global(global),
|
||||
|
@ -4057,12 +4057,14 @@ impl<'a> Codegen<'a> {
|
|||
let tty = vtarget.ty;
|
||||
|
||||
match self.tys.base_of(tty).unwrap_or(tty).expand() {
|
||||
ty::Kind::Module(m) => match self.find_type(pos, self.ci.file, m, Err(name)).expand() {
|
||||
ty::Kind::NEVER => Value::NEVER,
|
||||
ty::Kind::Global(global) => self.gen_global(global),
|
||||
ty::Kind::Const(cnst) => self.gen_const(cnst, ctx),
|
||||
v => Some(self.ci.nodes.new_const_lit(ty::Id::TYPE, v.compress())),
|
||||
},
|
||||
ty::Kind::Module(m) => {
|
||||
match self.find_type(pos, self.ci.file, m, self.ci.parent, Err(name)).expand() {
|
||||
ty::Kind::NEVER => Value::NEVER,
|
||||
ty::Kind::Global(global) => self.gen_global(global),
|
||||
ty::Kind::Const(cnst) => self.gen_const(cnst, ctx),
|
||||
v => Some(self.ci.nodes.new_const_lit(ty::Id::TYPE, v.compress())),
|
||||
}
|
||||
}
|
||||
ty::Kind::Enum(e) => {
|
||||
let intrnd = self.tys.names.project(name);
|
||||
self.gen_enum_variant(pos, e, intrnd)
|
||||
|
@ -4071,15 +4073,9 @@ impl<'a> Codegen<'a> {
|
|||
let Struct { ast, file, .. } = self.tys.ins.structs[s];
|
||||
if let Some((offset, ty)) = OffsetIter::offset_of(self.tys, s, name) {
|
||||
Some(Value::ptr(self.offset(vtarget.id, offset)).ty(ty))
|
||||
} else if let Expr::Struct { fields: [.., CommentOr::Or(Err(scope))], .. } =
|
||||
} else if let Expr::Struct { fields: [.., CommentOr::Or(Err(_))], .. } =
|
||||
ast.get(&self.files[file.index()])
|
||||
&& let ty = self.find_type_low(
|
||||
pos,
|
||||
self.ci.file,
|
||||
file,
|
||||
Some((s.into(), scope)),
|
||||
Err(name),
|
||||
)
|
||||
&& let ty = self.find_type(pos, self.ci.file, file, s.into(), Err(name))
|
||||
&& let ty::Kind::Func(_) = ty.expand()
|
||||
{
|
||||
return Some(Err((ty, vtarget)));
|
||||
|
@ -4109,21 +4105,8 @@ impl<'a> Codegen<'a> {
|
|||
.expand()
|
||||
{
|
||||
ty::Kind::Struct(s) => {
|
||||
let Struct { ast, file, .. } = self.tys.ins.structs[s];
|
||||
let Expr::Struct { fields: &[.., CommentOr::Or(Err(scope))], .. } =
|
||||
ast.get(&self.files[file.index()])
|
||||
else {
|
||||
self.error(
|
||||
pos,
|
||||
fa!("'{}' has not declarations", self.ty_display(s.into())),
|
||||
);
|
||||
return Value::NEVER.map(Ok);
|
||||
};
|
||||
|
||||
match self
|
||||
.find_type_low(pos, self.ci.file, file, Some((s.into(), scope)), Err(name))
|
||||
.expand()
|
||||
{
|
||||
let Struct { file, .. } = self.tys.ins.structs[s];
|
||||
match self.find_type(pos, self.ci.file, file, s.into(), Err(name)).expand() {
|
||||
ty::Kind::NEVER => Value::NEVER,
|
||||
ty::Kind::Global(global) => self.gen_global(global),
|
||||
ty::Kind::Const(cnst) => self.gen_const(cnst, ctx),
|
||||
|
@ -4131,7 +4114,7 @@ impl<'a> Codegen<'a> {
|
|||
}
|
||||
}
|
||||
ty::Kind::Module(m) => {
|
||||
match self.find_type(pos, self.ci.file, m, Err(name)).expand() {
|
||||
match self.find_type(pos, self.ci.file, m, m.into(), Err(name)).expand() {
|
||||
ty::Kind::NEVER => Value::NEVER,
|
||||
ty::Kind::Global(global) => self.gen_global(global),
|
||||
ty::Kind::Const(cnst) => self.gen_const(cnst, ctx),
|
||||
|
@ -4265,7 +4248,7 @@ impl<'a> Codegen<'a> {
|
|||
return Value::NEVER;
|
||||
};
|
||||
|
||||
let Func { expr, file, is_inline, .. } = self.tys.ins.funcs[fu];
|
||||
let Func { expr, file, is_inline, parent, .. } = self.tys.ins.funcs[fu];
|
||||
let ast = &self.files[file.index()];
|
||||
let &Expr::Closure { args: cargs, body, .. } = expr.get(ast) else { unreachable!() };
|
||||
|
||||
|
@ -4347,6 +4330,7 @@ impl<'a> Codegen<'a> {
|
|||
self.ci.inline_depth += 1;
|
||||
let prev_ret = self.ci.ret.replace(sig.ret);
|
||||
let prev_file = mem::replace(&mut self.ci.file, file);
|
||||
let prev_parent = mem::replace(&mut self.ci.parent, parent);
|
||||
let prev_ctrl = self.ci.ctrl.get();
|
||||
|
||||
if self.expr(body).is_some() {
|
||||
|
@ -4363,6 +4347,7 @@ impl<'a> Codegen<'a> {
|
|||
|
||||
self.ci.ret = prev_ret;
|
||||
self.ci.file = prev_file;
|
||||
self.ci.parent = prev_parent;
|
||||
self.ci.inline_depth -= 1;
|
||||
self.ci.inline_var_base = prev_var_base;
|
||||
self.ci.inline_aclass_base = prev_aclass_base;
|
||||
|
@ -5354,22 +5339,20 @@ impl<'a> Codegen<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
fn find_type_in_file(&mut self, pos: Pos, file: Module, id: Result<Ident, &str>) -> ty::Id {
|
||||
self.find_type(pos, file, file, file.into(), id)
|
||||
}
|
||||
|
||||
fn find_type_in_scope(&mut self, pos: Pos, id: Result<Ident, &str>) -> ty::Id {
|
||||
self.find_type(pos, self.ci.file, self.ci.file, self.ci.parent, id)
|
||||
}
|
||||
|
||||
fn find_type(
|
||||
&mut self,
|
||||
pos: Pos,
|
||||
from_file: Module,
|
||||
file: Module,
|
||||
id: Result<Ident, &str>,
|
||||
) -> ty::Id {
|
||||
self.find_type_low(pos, from_file, file, None, id)
|
||||
}
|
||||
|
||||
fn find_type_low(
|
||||
&mut self,
|
||||
pos: Pos,
|
||||
from_file: Module,
|
||||
file: Module,
|
||||
subscope: Option<(ty::Id, &[Expr])>,
|
||||
parent: ty::Id,
|
||||
id: Result<Ident, &str>,
|
||||
) -> ty::Id {
|
||||
let ty = if let Ok(id) = id
|
||||
|
@ -5384,9 +5367,24 @@ impl<'a> Codegen<'a> {
|
|||
} else {
|
||||
let f = &self.files[file.index()];
|
||||
|
||||
let Some((expr @ Expr::BinOp { left, right, .. }, name)) =
|
||||
parser::find_decl(subscope.map(|(_, s)| s).unwrap_or(f.exprs()), &f.file, id)
|
||||
else {
|
||||
let mut piter = parent;
|
||||
let Some((expr @ Expr::BinOp { left, right, .. }, name)) = (loop {
|
||||
if let Some(f) =
|
||||
parser::find_decl(self.tys.scope_of(piter, f).unwrap_or(f.exprs()), &f.file, id)
|
||||
{
|
||||
break Some(f);
|
||||
}
|
||||
|
||||
piter = match self.tys.parent_of(piter) {
|
||||
Some(p) => p,
|
||||
None => {
|
||||
if let ty::Kind::Struct(_) = parent.expand() {
|
||||
panic!();
|
||||
}
|
||||
break None;
|
||||
}
|
||||
};
|
||||
}) else {
|
||||
return match id {
|
||||
Ok(_) => {
|
||||
debug_assert_eq!(from_file, file);
|
||||
|
@ -5421,22 +5419,10 @@ impl<'a> Codegen<'a> {
|
|||
self.tys
|
||||
.ins
|
||||
.consts
|
||||
.push(Const {
|
||||
ast: ExprRef::new(expr),
|
||||
name,
|
||||
file,
|
||||
parent: subscope.map(|(p, _)| p).unwrap_or(file.into()),
|
||||
})
|
||||
.push(Const { ast: ExprRef::new(expr), name, file, parent })
|
||||
.into()
|
||||
} else {
|
||||
self.parse_ty(
|
||||
TyScope {
|
||||
file,
|
||||
parent: subscope.map(|(p, _)| p).unwrap_or(file.into()),
|
||||
name: Some(name),
|
||||
},
|
||||
right,
|
||||
)
|
||||
self.parse_ty(TyScope { file, parent, name: Some(name) }, right)
|
||||
},
|
||||
)
|
||||
})
|
||||
|
@ -5491,11 +5477,11 @@ impl<'a> Codegen<'a> {
|
|||
self.tys.make_opt(base)
|
||||
}
|
||||
Expr::Ident { id, .. } if let Ok(bt) = ty::Builtin::try_from(id) => bt.into(),
|
||||
Expr::Ident { id, pos, .. } => self.find_type(pos, sc.file, sc.file, Ok(id)),
|
||||
Expr::Ident { id, pos, .. } => self.find_type(pos, sc.file, sc.file, sc.parent, Ok(id)),
|
||||
Expr::Field { target, pos, name }
|
||||
if let ty::Kind::Module(inside) = self.parse_ty(sc.anon(), target).expand() =>
|
||||
{
|
||||
self.find_type(pos, sc.file, inside, Err(name))
|
||||
self.find_type(pos, sc.file, inside, inside.into(), Err(name))
|
||||
}
|
||||
Expr::Directive { name: "TypeOf", args: [expr], .. } => self.infer_type(expr),
|
||||
Expr::Slice { size: None, item, .. } => {
|
||||
|
|
Loading…
Reference in a new issue