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