aaaaaaaaaaaaaaaa
This commit is contained in:
parent
1bde8f3ccd
commit
4c7813aa98
553
src/ast2/ir.rs
553
src/ast2/ir.rs
File diff suppressed because it is too large
Load diff
|
@ -18,6 +18,7 @@ pub mod intern;
|
||||||
pub mod ir;
|
pub mod ir;
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
pub mod tag;
|
pub mod tag;
|
||||||
|
pub mod typecheck;
|
||||||
pub mod visitor;
|
pub mod visitor;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
|
|
@ -328,8 +328,8 @@ impl AstNodeExt for Ast {
|
||||||
AstNode::Assign { lhs, rhs }
|
AstNode::Assign { lhs, rhs }
|
||||||
}
|
}
|
||||||
Tag::SubscriptExpr => {
|
Tag::SubscriptExpr => {
|
||||||
let (lhs, rhs) = data.as_two_indices();
|
let (lhs, index) = data.as_two_indices();
|
||||||
AstNode::SubscriptExpr { lhs, rhs }
|
AstNode::SubscriptExpr { lhs, index }
|
||||||
}
|
}
|
||||||
Tag::IfExpr => {
|
Tag::IfExpr => {
|
||||||
let (cond, body) = data.as_two_indices();
|
let (cond, body) = data.as_two_indices();
|
||||||
|
@ -609,7 +609,7 @@ pub enum AstNode {
|
||||||
},
|
},
|
||||||
SubscriptExpr {
|
SubscriptExpr {
|
||||||
lhs: Index,
|
lhs: Index,
|
||||||
rhs: Index,
|
index: Index,
|
||||||
},
|
},
|
||||||
IfExpr {
|
IfExpr {
|
||||||
cond: Index,
|
cond: Index,
|
||||||
|
|
330
src/ast2/typecheck.rs
Normal file
330
src/ast2/typecheck.rs
Normal file
|
@ -0,0 +1,330 @@
|
||||||
|
use crate::variant;
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
intern::{self},
|
||||||
|
tag::{AstNode, AstNodeExt},
|
||||||
|
visitor::{AstExt, AstVisitorTrait},
|
||||||
|
Ast, Data, Index, Tag,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
enum ErrorKind {
|
||||||
|
MismatchingTypes,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
struct Error {
|
||||||
|
idx: Index,
|
||||||
|
kind: ErrorKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TypeChecker<'a> {
|
||||||
|
ip: &'a mut intern::InternPool,
|
||||||
|
errors: Vec<Error>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> TypeChecker<'a> {
|
||||||
|
fn visit_children<'b>(
|
||||||
|
&mut self,
|
||||||
|
ast: &'b mut super::Ast,
|
||||||
|
idx: Index,
|
||||||
|
) -> Result<Option<intern::Index>, ()> {
|
||||||
|
for child in ast.get_node_children(idx) {
|
||||||
|
self.visit_any(ast, child)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: actually handle errors here instead of aborting.
|
||||||
|
impl<'a> AstVisitorTrait<&'a mut Ast> for TypeChecker<'_> {
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
type Value = Option<intern::Index>;
|
||||||
|
|
||||||
|
const UNIMPL: Self::Error = ();
|
||||||
|
|
||||||
|
fn visit_parameter_impl(
|
||||||
|
&mut self,
|
||||||
|
ast: &'a mut Ast,
|
||||||
|
idx: Index,
|
||||||
|
ty: Index,
|
||||||
|
name: intern::Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = (idx, name);
|
||||||
|
self.visit_any(ast, ty)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_array_type_impl(
|
||||||
|
&mut self,
|
||||||
|
ast: &'a mut Ast,
|
||||||
|
idx: Index,
|
||||||
|
length: Index,
|
||||||
|
pointer: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
_ = self.visit_any(ast, length)?;
|
||||||
|
let pointee = self.visit_any(ast, pointer)?.expect("no type?");
|
||||||
|
|
||||||
|
variant!(self.ip.get_key(pointee) => intern::Key::PointerType { pointee, flags });
|
||||||
|
|
||||||
|
// get interened value from constant node
|
||||||
|
let length = {
|
||||||
|
let value = ast.datas[length].as_index_intern().1;
|
||||||
|
|
||||||
|
match self.ip.get_key(value) {
|
||||||
|
intern::Key::SIntSmall { bits } => bits as u32,
|
||||||
|
intern::Key::UIntSmall { bits } => bits as u32,
|
||||||
|
intern::Key::SInt64 { bits } => bits as u32,
|
||||||
|
intern::Key::UInt64 { bits } => bits as u32,
|
||||||
|
intern::Key::NegativeInt { bigint } | intern::Key::PositiveInt { bigint } => {
|
||||||
|
bigint.iter_u32_digits().next().unwrap_or(0)
|
||||||
|
}
|
||||||
|
_ => 0,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let ty = self.ip.get_array_type(pointee, Some(flags), length);
|
||||||
|
ast.tags[idx] = Tag::InternedType;
|
||||||
|
ast.datas[idx] = Data::intern(ty);
|
||||||
|
|
||||||
|
Ok(Some(ty))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_pointer_type_impl(
|
||||||
|
&mut self,
|
||||||
|
ast: &'a mut Ast,
|
||||||
|
idx: Index,
|
||||||
|
ty: Index,
|
||||||
|
flags: intern::PointerFlags,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
let pointee = self.visit_any(ast, ty)?.expect("no type?");
|
||||||
|
|
||||||
|
let ty = self.ip.get_pointer_type(pointee, Some(flags));
|
||||||
|
|
||||||
|
ast.tags[idx] = Tag::InternedType;
|
||||||
|
ast.datas[idx] = Data::intern(ty);
|
||||||
|
|
||||||
|
Ok(Some(ty))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_type_decl_ref_impl(
|
||||||
|
&mut self,
|
||||||
|
ast: &'a mut Ast,
|
||||||
|
idx: Index,
|
||||||
|
decl: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
let ty = self.visit_any(ast, decl)?.expect("no type?");
|
||||||
|
|
||||||
|
ast.tags[idx] = Tag::InternedType;
|
||||||
|
ast.datas[idx] = Data::intern(ty);
|
||||||
|
|
||||||
|
Ok(Some(ty))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_function_proto_impl(
|
||||||
|
&mut self,
|
||||||
|
ast: &'a mut Ast,
|
||||||
|
idx: Index,
|
||||||
|
name: intern::Index,
|
||||||
|
return_type: Index,
|
||||||
|
parameter_list: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
variant!(ast.get_ast_node(parameter_list) => AstNode::ParameterList { params });
|
||||||
|
|
||||||
|
let return_type = self.visit_any(ast, return_type)?.expect("no type?");
|
||||||
|
|
||||||
|
let params = params
|
||||||
|
.into_iter()
|
||||||
|
.map(|param| self.visit_parameter(ast, param).map(|a| a.unwrap()))
|
||||||
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
|
let ty = self.ip.get_function_type(return_type, params);
|
||||||
|
|
||||||
|
ast.tags[idx] = Tag::FunctionProtoInterned;
|
||||||
|
ast.datas[idx] = Data::two_interns(name, ty);
|
||||||
|
|
||||||
|
Ok(Some(ty))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_function_proto_interned_impl(
|
||||||
|
&mut self,
|
||||||
|
ast: &'a mut Ast,
|
||||||
|
idx: Index,
|
||||||
|
name: intern::Index,
|
||||||
|
ty: intern::Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
Ok(Some(ty))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_struct_decl_impl(
|
||||||
|
&mut self,
|
||||||
|
ast: &'a mut Ast,
|
||||||
|
idx: Index,
|
||||||
|
name: intern::Index,
|
||||||
|
flags: intern::StructFlags,
|
||||||
|
field_names: Vec<intern::Index>,
|
||||||
|
field_types: Vec<Index>,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
let types = field_types
|
||||||
|
.into_iter()
|
||||||
|
.map(|i| self.visit_any(ast, i).map(Option::unwrap))
|
||||||
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
|
let ty = self.ip.insert_or_replace_struct_type(
|
||||||
|
name,
|
||||||
|
idx,
|
||||||
|
flags.packed,
|
||||||
|
flags.c_like,
|
||||||
|
field_names.into_iter().zip(types),
|
||||||
|
);
|
||||||
|
|
||||||
|
ast.tags[idx] = Tag::StructDeclInterned;
|
||||||
|
ast.datas[idx] = Data::two_interns(name, ty);
|
||||||
|
|
||||||
|
Ok(Some(ty))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_function_decl_impl(
|
||||||
|
&mut self,
|
||||||
|
ast: &'a mut Ast,
|
||||||
|
idx: Index,
|
||||||
|
proto: Index,
|
||||||
|
body: Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
let ty = self.visit_any(ast, proto)?.expect("no type?");
|
||||||
|
let body = self.visit_block(ast, body)?.unwrap_or(intern::Index::VOID);
|
||||||
|
|
||||||
|
let ret_ty = self.ip.try_get_return_type(ty).expect("no type?");
|
||||||
|
|
||||||
|
if body != ret_ty {
|
||||||
|
self.errors.push(Error {
|
||||||
|
idx,
|
||||||
|
kind: ErrorKind::MismatchingTypes,
|
||||||
|
});
|
||||||
|
Ok(Some(intern::Index::VOID))
|
||||||
|
} else {
|
||||||
|
Ok(Some(ty))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_block_impl(
|
||||||
|
&mut self,
|
||||||
|
ast: &'a mut Ast,
|
||||||
|
idx: Index,
|
||||||
|
statements: Vec<Index>,
|
||||||
|
expr: Option<Index>,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
for stmt in statements {
|
||||||
|
self.visit_any(ast, stmt)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
expr.map(|expr| self.visit_any(ast, expr))
|
||||||
|
.transpose()
|
||||||
|
.map(Option::flatten)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_file_impl(
|
||||||
|
&mut self,
|
||||||
|
ast: &'a mut Ast,
|
||||||
|
idx: Index,
|
||||||
|
decls: Vec<Index>,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
for decl in decls {
|
||||||
|
self.visit_any(ast, decl)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_struct_decl_interned_impl(
|
||||||
|
&mut self,
|
||||||
|
ast: &'a mut Ast,
|
||||||
|
idx: Index,
|
||||||
|
name: intern::Index,
|
||||||
|
ty: intern::Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
Ok(Some(ty))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_any(
|
||||||
|
&mut self,
|
||||||
|
ast: &'a mut Ast,
|
||||||
|
idx: super::Index,
|
||||||
|
) -> Result<Self::Value, Self::Error> {
|
||||||
|
let (tag, data) = ast.get_node_tag_and_data(idx);
|
||||||
|
|
||||||
|
let _ty = match tag {
|
||||||
|
Tag::Root => unreachable!(),
|
||||||
|
Tag::InternedType => Some(data.as_intern()),
|
||||||
|
Tag::File => self.visit_children(ast, idx)?,
|
||||||
|
Tag::ArrayType => self.visit_array_type(ast, idx)?,
|
||||||
|
Tag::PointerType => self.visit_pointer_type(ast, idx)?,
|
||||||
|
Tag::TypeDeclRef => self.visit_type_decl_ref(ast, idx)?,
|
||||||
|
Tag::FunctionProtoInterned => self.visit_function_proto_interned(ast, idx)?,
|
||||||
|
Tag::FunctionProto => self.visit_function_proto(ast, idx)?,
|
||||||
|
Tag::Parameter => self.visit_parameter(ast, idx)?,
|
||||||
|
Tag::StructDecl => self.visit_struct_decl(ast, idx)?,
|
||||||
|
Tag::StructDeclInterned => {
|
||||||
|
let (_, ty) = data.as_two_interns();
|
||||||
|
|
||||||
|
Some(ty)
|
||||||
|
}
|
||||||
|
Tag::FunctionDecl => self.visit_function_decl(ast, idx)?,
|
||||||
|
Tag::ParameterList => todo!(),
|
||||||
|
Tag::Block => todo!(),
|
||||||
|
Tag::BlockTrailingExpr => todo!(),
|
||||||
|
Tag::Constant => todo!(),
|
||||||
|
Tag::ExprStmt => todo!(),
|
||||||
|
Tag::ReturnStmt => todo!(),
|
||||||
|
Tag::ReturnExprStmt => todo!(),
|
||||||
|
Tag::VarDecl => todo!(),
|
||||||
|
Tag::MutVarDecl => todo!(),
|
||||||
|
Tag::VarDeclAssignment => todo!(),
|
||||||
|
Tag::MutVarDeclAssignment => todo!(),
|
||||||
|
Tag::GlobalDecl => todo!(),
|
||||||
|
Tag::FieldDecl => todo!(),
|
||||||
|
Tag::DeclRef => todo!(),
|
||||||
|
Tag::DeclRefUnresolved => todo!(),
|
||||||
|
Tag::TypeDeclRefUnresolved => todo!(),
|
||||||
|
Tag::CallExpr => todo!(),
|
||||||
|
Tag::FieldAccess => todo!(),
|
||||||
|
Tag::ArgumentList => todo!(),
|
||||||
|
Tag::Argument => todo!(),
|
||||||
|
Tag::NamedArgument => todo!(),
|
||||||
|
Tag::ExplicitCast => todo!(),
|
||||||
|
Tag::Deref => todo!(),
|
||||||
|
Tag::AddressOf => todo!(),
|
||||||
|
Tag::Not => todo!(),
|
||||||
|
Tag::Negate => todo!(),
|
||||||
|
Tag::PlaceToValueConversion => todo!(),
|
||||||
|
Tag::ValueToPlaceConversion => todo!(),
|
||||||
|
Tag::Or => todo!(),
|
||||||
|
Tag::And => todo!(),
|
||||||
|
Tag::BitOr => todo!(),
|
||||||
|
Tag::BitXOr => todo!(),
|
||||||
|
Tag::BitAnd => todo!(),
|
||||||
|
Tag::Eq => todo!(),
|
||||||
|
Tag::NEq => todo!(),
|
||||||
|
Tag::Lt => todo!(),
|
||||||
|
Tag::Gt => todo!(),
|
||||||
|
Tag::Le => todo!(),
|
||||||
|
Tag::Ge => todo!(),
|
||||||
|
Tag::Shl => todo!(),
|
||||||
|
Tag::Shr => todo!(),
|
||||||
|
Tag::Add => todo!(),
|
||||||
|
Tag::Sub => todo!(),
|
||||||
|
Tag::Mul => todo!(),
|
||||||
|
Tag::Div => todo!(),
|
||||||
|
Tag::Rem => todo!(),
|
||||||
|
Tag::Assign => todo!(),
|
||||||
|
Tag::SubscriptExpr => todo!(),
|
||||||
|
Tag::IfExpr => todo!(),
|
||||||
|
Tag::IfElseExpr => todo!(),
|
||||||
|
Tag::Error => todo!(),
|
||||||
|
Tag::Undefined => todo!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
|
@ -279,314 +279,347 @@ pub trait AstVisitorTrait<Ast: AstExt + AstNodeExt> {
|
||||||
type Value;
|
type Value;
|
||||||
const UNIMPL: Self::Error;
|
const UNIMPL: Self::Error;
|
||||||
|
|
||||||
fn visit_function_decl(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
tag_visit_fn!(
|
||||||
_ = (ast, idx);
|
File {
|
||||||
Err(Self::UNIMPL)
|
decls: Vec<Index>,
|
||||||
}
|
},
|
||||||
fn visit_parameter(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
FunctionProto {
|
||||||
_ = (ast, idx);
|
name: Interned,
|
||||||
Err(Self::UNIMPL)
|
return_type: Index,
|
||||||
}
|
parameter_list: Index,
|
||||||
fn visit_parameter_list(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
},
|
||||||
_ = (ast, idx);
|
FunctionProtoInterned {
|
||||||
Err(Self::UNIMPL)
|
name: Interned,
|
||||||
}
|
ty: Interned,
|
||||||
fn visit_block(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
},
|
||||||
_ = (ast, idx);
|
FunctionDecl {
|
||||||
Err(Self::UNIMPL)
|
proto: Index,
|
||||||
}
|
body: Index,
|
||||||
fn visit_block_trailing_expr(
|
},
|
||||||
&mut self,
|
ParameterList {
|
||||||
ast: Ast,
|
params: Vec<Index>,
|
||||||
idx: Index,
|
},
|
||||||
) -> Result<Self::Value, Self::Error> {
|
Parameter {
|
||||||
_ = (ast, idx);
|
ty: Index,
|
||||||
Err(Self::UNIMPL)
|
name: Interned,
|
||||||
}
|
},
|
||||||
fn visit_block_maybe_trailing(
|
Block {
|
||||||
&mut self,
|
statements: Vec<Index>,
|
||||||
ast: Ast,
|
expr: Option<Index>,
|
||||||
idx: Index,
|
},
|
||||||
) -> Result<Self::Value, Self::Error> {
|
Constant {
|
||||||
match ast.get_node_tag_and_data(idx).0 {
|
ty: Index,
|
||||||
Tag::BlockTrailingExpr => self.visit_block_trailing_expr(ast, idx),
|
value: Interned,
|
||||||
Tag::Block => self.visit_block(ast, idx),
|
},
|
||||||
_ => unreachable!(),
|
ExprStmt {
|
||||||
}
|
expr: Index,
|
||||||
}
|
},
|
||||||
fn visit_function_proto(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
ReturnStmt {},
|
||||||
_ = (ast, idx);
|
ReturnExprStmt {
|
||||||
Err(Self::UNIMPL)
|
expr: Index,
|
||||||
}
|
},
|
||||||
fn visit_call_expr(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
VarDecl {
|
||||||
_ = (ast, idx);
|
name: Interned,
|
||||||
Err(Self::UNIMPL)
|
ty: Index,
|
||||||
}
|
},
|
||||||
fn visit_add_expr(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
MutVarDecl {
|
||||||
_ = (ast, idx);
|
name: Interned,
|
||||||
Err(Self::UNIMPL)
|
ty: Index,
|
||||||
}
|
},
|
||||||
fn visit_sub_expr(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
VarDeclAssignment {
|
||||||
_ = (ast, idx);
|
name: Interned,
|
||||||
Err(Self::UNIMPL)
|
expr: Index,
|
||||||
}
|
ty: Option<Index>,
|
||||||
fn visit_mul_expr(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
},
|
||||||
_ = (ast, idx);
|
MutVarDeclAssignment {
|
||||||
Err(Self::UNIMPL)
|
name: Interned,
|
||||||
}
|
expr: Index,
|
||||||
fn visit_div_expr(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
ty: Option<Index>,
|
||||||
_ = (ast, idx);
|
},
|
||||||
Err(Self::UNIMPL)
|
GlobalDecl {
|
||||||
}
|
name: Interned,
|
||||||
fn visit_rem_expr(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
expr: Index,
|
||||||
_ = (ast, idx);
|
ty: Index,
|
||||||
Err(Self::UNIMPL)
|
},
|
||||||
}
|
StructDecl {
|
||||||
fn visit_eq_expr(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
name: Interned,
|
||||||
_ = (ast, idx);
|
flags: StructFlags,
|
||||||
Err(Self::UNIMPL)
|
field_names: Vec<Interned>,
|
||||||
}
|
field_types: Vec<Index>,
|
||||||
fn visit_neq_expr(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
},
|
||||||
_ = (ast, idx);
|
StructDeclInterned {
|
||||||
Err(Self::UNIMPL)
|
name: Interned,
|
||||||
}
|
ty: Interned,
|
||||||
fn visit_lt_expr(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
},
|
||||||
_ = (ast, idx);
|
FieldDecl {
|
||||||
Err(Self::UNIMPL)
|
name: Interned,
|
||||||
}
|
ty: Index,
|
||||||
fn visit_gt_expr(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
},
|
||||||
_ = (ast, idx);
|
DeclRef {
|
||||||
Err(Self::UNIMPL)
|
decl: Index,
|
||||||
}
|
},
|
||||||
fn visit_le_expr(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
DeclRefUnresolved {
|
||||||
_ = (ast, idx);
|
scope: Index,
|
||||||
Err(Self::UNIMPL)
|
name: Interned,
|
||||||
}
|
},
|
||||||
fn visit_ge_expr(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
InternedType {
|
||||||
_ = (ast, idx);
|
intern: Interned,
|
||||||
Err(Self::UNIMPL)
|
},
|
||||||
}
|
TypeDeclRef {
|
||||||
fn visit_shl_expr(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
decl: Index,
|
||||||
_ = (ast, idx);
|
},
|
||||||
Err(Self::UNIMPL)
|
TypeDeclRefUnresolved {
|
||||||
}
|
scope: Index,
|
||||||
fn visit_shr_expr(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
name: Interned,
|
||||||
_ = (ast, idx);
|
},
|
||||||
Err(Self::UNIMPL)
|
PointerType {
|
||||||
}
|
ty: Index,
|
||||||
fn visit_bitor_expr(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
flags: PointerFlags,
|
||||||
_ = (ast, idx);
|
},
|
||||||
Err(Self::UNIMPL)
|
ArrayType {
|
||||||
}
|
length: Index,
|
||||||
fn visit_bitxor_expr(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
pointer: Index,
|
||||||
_ = (ast, idx);
|
},
|
||||||
Err(Self::UNIMPL)
|
CallExpr {
|
||||||
}
|
func: Index,
|
||||||
fn visit_bitand_expr(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
argument_list: Index,
|
||||||
_ = (ast, idx);
|
},
|
||||||
Err(Self::UNIMPL)
|
FieldAccess {
|
||||||
}
|
field_name: Interned,
|
||||||
fn visit_or_expr(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
expr: Index,
|
||||||
_ = (ast, idx);
|
},
|
||||||
Err(Self::UNIMPL)
|
ArgumentList {
|
||||||
}
|
arguments: Vec<Index>,
|
||||||
fn visit_and_expr(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
},
|
||||||
_ = (ast, idx);
|
Argument {
|
||||||
Err(Self::UNIMPL)
|
expr: Index,
|
||||||
}
|
name: Option<Interned>,
|
||||||
fn visit_not_expr(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
},
|
||||||
_ = (ast, idx);
|
ExplicitCast {
|
||||||
Err(Self::UNIMPL)
|
expr: Index,
|
||||||
}
|
ty: Index,
|
||||||
fn visit_negate_expr(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
},
|
||||||
_ = (ast, idx);
|
Deref {
|
||||||
Err(Self::UNIMPL)
|
expr: Index,
|
||||||
}
|
},
|
||||||
fn visit_deref_expr(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
AddressOf {
|
||||||
_ = (ast, idx);
|
expr: Index,
|
||||||
Err(Self::UNIMPL)
|
},
|
||||||
}
|
Not {
|
||||||
fn visit_address_of_expr(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
expr: Index,
|
||||||
_ = (ast, idx);
|
},
|
||||||
Err(Self::UNIMPL)
|
Negate {
|
||||||
}
|
expr: Index,
|
||||||
fn visit_explicit_cast_expr(
|
},
|
||||||
&mut self,
|
PlaceToValueConversion {
|
||||||
ast: Ast,
|
expr: Index,
|
||||||
idx: Index,
|
},
|
||||||
) -> Result<Self::Value, Self::Error> {
|
ValueToPlaceConversion {
|
||||||
_ = (ast, idx);
|
expr: Index,
|
||||||
Err(Self::UNIMPL)
|
},
|
||||||
}
|
Or {
|
||||||
fn visit_assign(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
lhs: Index,
|
||||||
_ = (ast, idx);
|
rhs: Index,
|
||||||
Err(Self::UNIMPL)
|
},
|
||||||
}
|
And {
|
||||||
fn visit_subscript_expr(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
lhs: Index,
|
||||||
_ = (ast, idx);
|
rhs: Index,
|
||||||
Err(Self::UNIMPL)
|
},
|
||||||
}
|
BitOr {
|
||||||
fn visit_if_expr(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
lhs: Index,
|
||||||
_ = (ast, idx);
|
rhs: Index,
|
||||||
Err(Self::UNIMPL)
|
},
|
||||||
}
|
BitXOr {
|
||||||
fn visit_if_else_expr(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
lhs: Index,
|
||||||
_ = (ast, idx);
|
rhs: Index,
|
||||||
Err(Self::UNIMPL)
|
},
|
||||||
}
|
BitAnd {
|
||||||
fn visit_argument(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
lhs: Index,
|
||||||
_ = (ast, idx);
|
rhs: Index,
|
||||||
Err(Self::UNIMPL)
|
},
|
||||||
}
|
Eq {
|
||||||
|
lhs: Index,
|
||||||
fn visit_any_argument(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
rhs: Index,
|
||||||
match ast.get_node_tag_and_data(idx).0 {
|
},
|
||||||
Tag::Argument => self.visit_argument(ast, idx),
|
NEq {
|
||||||
Tag::NamedArgument => self.visit_named_argument(ast, idx),
|
lhs: Index,
|
||||||
_ => unreachable!(),
|
rhs: Index,
|
||||||
}
|
},
|
||||||
}
|
Lt {
|
||||||
|
lhs: Index,
|
||||||
fn visit_named_argument(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
rhs: Index,
|
||||||
_ = (ast, idx);
|
},
|
||||||
Err(Self::UNIMPL)
|
Gt {
|
||||||
}
|
lhs: Index,
|
||||||
|
rhs: Index,
|
||||||
fn visit_argument_list(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
},
|
||||||
_ = (ast, idx);
|
Le {
|
||||||
Err(Self::UNIMPL)
|
lhs: Index,
|
||||||
}
|
rhs: Index,
|
||||||
|
},
|
||||||
fn visit_constant(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
Ge {
|
||||||
_ = (ast, idx);
|
lhs: Index,
|
||||||
Err(Self::UNIMPL)
|
rhs: Index,
|
||||||
}
|
},
|
||||||
|
Shl {
|
||||||
fn visit_return(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
lhs: Index,
|
||||||
_ = (ast, idx);
|
rhs: Index,
|
||||||
Err(Self::UNIMPL)
|
},
|
||||||
}
|
Shr {
|
||||||
fn visit_return_expr(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
lhs: Index,
|
||||||
_ = (ast, idx);
|
rhs: Index,
|
||||||
Err(Self::UNIMPL)
|
},
|
||||||
}
|
Add {
|
||||||
fn visit_global_decl(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
lhs: Index,
|
||||||
_ = (ast, idx);
|
rhs: Index,
|
||||||
Err(Self::UNIMPL)
|
},
|
||||||
}
|
Sub {
|
||||||
fn visit_var_decl(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
lhs: Index,
|
||||||
_ = (ast, idx);
|
rhs: Index,
|
||||||
Err(Self::UNIMPL)
|
},
|
||||||
}
|
Mul {
|
||||||
fn visit_mut_var_decl(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
lhs: Index,
|
||||||
_ = (ast, idx);
|
rhs: Index,
|
||||||
Err(Self::UNIMPL)
|
},
|
||||||
}
|
Div {
|
||||||
fn visit_var_assign_decl(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
lhs: Index,
|
||||||
_ = (ast, idx);
|
rhs: Index,
|
||||||
Err(Self::UNIMPL)
|
},
|
||||||
}
|
Rem {
|
||||||
fn visit_mut_var_assign_decl(
|
lhs: Index,
|
||||||
&mut self,
|
rhs: Index,
|
||||||
ast: Ast,
|
},
|
||||||
idx: Index,
|
Assign {
|
||||||
) -> Result<Self::Value, Self::Error> {
|
lhs: Index,
|
||||||
_ = (ast, idx);
|
rhs: Index,
|
||||||
Err(Self::UNIMPL)
|
},
|
||||||
}
|
SubscriptExpr {
|
||||||
fn visit_decl_ref(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
lhs: Index,
|
||||||
_ = (ast, idx);
|
index: Index,
|
||||||
Err(Self::UNIMPL)
|
},
|
||||||
}
|
IfExpr {
|
||||||
fn visit_value_to_place_conversion(
|
cond: Index,
|
||||||
&mut self,
|
body: Index,
|
||||||
ast: Ast,
|
},
|
||||||
idx: Index,
|
IfElseExpr {
|
||||||
) -> Result<Self::Value, Self::Error> {
|
cond: Index,
|
||||||
let idx = ast
|
a: Index,
|
||||||
.get_node_data_for_tag(idx, Tag::ValueToPlaceConversion)
|
b: Index,
|
||||||
.unwrap()
|
},
|
||||||
.as_index();
|
Error {
|
||||||
self.visit_any(ast, idx)
|
err: ParseError,
|
||||||
}
|
},
|
||||||
fn visit_place_to_value_conversion(
|
Undefined {},
|
||||||
&mut self,
|
);
|
||||||
ast: Ast,
|
|
||||||
idx: Index,
|
|
||||||
) -> Result<Self::Value, Self::Error> {
|
|
||||||
let idx = ast
|
|
||||||
.get_node_data_for_tag(idx, Tag::PlaceToValueConversion)
|
|
||||||
.unwrap()
|
|
||||||
.as_index();
|
|
||||||
self.visit_any(ast, idx)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_any(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
fn visit_any(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
match ast.get_node_tag_and_data(idx).0 {
|
match ast.get_ast_node(idx) {
|
||||||
Tag::FunctionProto => self.visit_function_proto(ast, idx),
|
AstNode::File { decls } => self.visit_file_impl(ast, idx, decls),
|
||||||
Tag::FunctionDecl => self.visit_function_decl(ast, idx),
|
AstNode::FunctionProto {
|
||||||
Tag::ParameterList => self.visit_parameter_list(ast, idx),
|
name,
|
||||||
Tag::Parameter => self.visit_parameter(ast, idx),
|
return_type,
|
||||||
Tag::Block => self.visit_block(ast, idx),
|
parameter_list,
|
||||||
Tag::BlockTrailingExpr => self.visit_block_trailing_expr(ast, idx),
|
} => self.visit_function_proto_impl(ast, idx, name, return_type, parameter_list),
|
||||||
Tag::Constant => self.visit_constant(ast, idx),
|
AstNode::FunctionProtoInterned { name, ty } => {
|
||||||
Tag::ExprStmt => todo!(),
|
self.visit_function_proto_interned_impl(ast, idx, name, ty)
|
||||||
Tag::ReturnStmt => self.visit_return(ast, idx),
|
}
|
||||||
Tag::ReturnExprStmt => self.visit_return_expr(ast, idx),
|
AstNode::FunctionDecl { proto, body } => {
|
||||||
Tag::VarDecl => self.visit_var_decl(ast, idx),
|
self.visit_function_decl_impl(ast, idx, proto, body)
|
||||||
Tag::MutVarDecl => self.visit_mut_var_decl(ast, idx),
|
}
|
||||||
Tag::VarDeclAssignment => self.visit_var_assign_decl(ast, idx),
|
AstNode::ParameterList { params } => self.visit_parameter_list_impl(ast, idx, params),
|
||||||
Tag::MutVarDeclAssignment => self.visit_mut_var_assign_decl(ast, idx),
|
AstNode::Parameter { ty, name } => self.visit_parameter_impl(ast, idx, ty, name),
|
||||||
Tag::GlobalDecl => self.visit_global_decl(ast, idx),
|
AstNode::Block { statements, expr } => {
|
||||||
Tag::StructDecl => todo!(),
|
self.visit_block_impl(ast, idx, statements, expr)
|
||||||
Tag::StructDeclInterned => todo!(),
|
}
|
||||||
Tag::FunctionProtoInterned => todo!(),
|
AstNode::Constant { ty, value } => self.visit_constant_impl(ast, idx, ty, value),
|
||||||
Tag::FieldDecl => todo!(),
|
AstNode::ExprStmt { expr } => self.visit_expr_stmt_impl(ast, idx, expr),
|
||||||
Tag::DeclRef => self.visit_decl_ref(ast, idx),
|
AstNode::ReturnStmt => self.visit_return_stmt_impl(ast, idx),
|
||||||
Tag::DeclRefUnresolved => todo!(),
|
AstNode::ReturnExprStmt { expr } => self.visit_return_expr_stmt_impl(ast, idx, expr),
|
||||||
Tag::InternedType => todo!(),
|
AstNode::VarDecl { name, ty } => self.visit_var_decl_impl(ast, idx, name, ty),
|
||||||
Tag::TypeDeclRef => todo!(),
|
AstNode::MutVarDecl { name, ty } => self.visit_mut_var_decl_impl(ast, idx, name, ty),
|
||||||
Tag::TypeDeclRefUnresolved => todo!(),
|
AstNode::VarDeclAssignment { name, expr, ty } => {
|
||||||
Tag::PointerType => todo!(),
|
self.visit_var_decl_assignment_impl(ast, idx, name, expr, ty)
|
||||||
Tag::ArrayType => todo!(),
|
}
|
||||||
Tag::CallExpr => self.visit_call_expr(ast, idx),
|
AstNode::MutVarDeclAssignment { name, expr, ty } => {
|
||||||
Tag::FieldAccess => todo!(),
|
self.visit_mut_var_decl_assignment_impl(ast, idx, name, expr, ty)
|
||||||
Tag::ArgumentList => self.visit_argument_list(ast, idx),
|
}
|
||||||
Tag::Argument => self.visit_argument(ast, idx),
|
AstNode::GlobalDecl { name, expr, ty } => {
|
||||||
Tag::NamedArgument => self.visit_named_argument(ast, idx),
|
self.visit_global_decl_impl(ast, idx, name, expr, ty)
|
||||||
Tag::ExplicitCast => self.visit_explicit_cast_expr(ast, idx),
|
}
|
||||||
Tag::Deref => self.visit_deref_expr(ast, idx),
|
AstNode::StructDecl {
|
||||||
Tag::AddressOf => self.visit_add_expr(ast, idx),
|
name,
|
||||||
Tag::Not => self.visit_not_expr(ast, idx),
|
flags,
|
||||||
Tag::Negate => self.visit_negate_expr(ast, idx),
|
field_names,
|
||||||
Tag::Or => self.visit_or_expr(ast, idx),
|
field_types,
|
||||||
Tag::And => self.visit_and_expr(ast, idx),
|
} => self.visit_struct_decl_impl(ast, idx, name, flags, field_names, field_types),
|
||||||
Tag::BitOr => self.visit_bitor_expr(ast, idx),
|
AstNode::StructDeclInterned { name, ty } => {
|
||||||
Tag::BitXOr => self.visit_bitxor_expr(ast, idx),
|
self.visit_struct_decl_interned_impl(ast, idx, name, ty)
|
||||||
Tag::BitAnd => self.visit_bitand_expr(ast, idx),
|
}
|
||||||
Tag::Eq => self.visit_eq_expr(ast, idx),
|
AstNode::FieldDecl { name, ty } => self.visit_field_decl_impl(ast, idx, name, ty),
|
||||||
Tag::NEq => self.visit_neq_expr(ast, idx),
|
AstNode::DeclRef { decl } => self.visit_decl_ref_impl(ast, idx, decl),
|
||||||
Tag::Lt => self.visit_lt_expr(ast, idx),
|
AstNode::DeclRefUnresolved { scope, name } => {
|
||||||
Tag::Gt => self.visit_gt_expr(ast, idx),
|
self.visit_decl_ref_unresolved_impl(ast, idx, scope, name)
|
||||||
Tag::Le => self.visit_le_expr(ast, idx),
|
}
|
||||||
Tag::Ge => self.visit_ge_expr(ast, idx),
|
AstNode::InternedType { intern } => self.visit_interned_type_impl(ast, idx, intern),
|
||||||
Tag::Shl => self.visit_shl_expr(ast, idx),
|
AstNode::TypeDeclRef { decl } => self.visit_type_decl_ref_impl(ast, idx, decl),
|
||||||
Tag::Shr => self.visit_shr_expr(ast, idx),
|
AstNode::TypeDeclRefUnresolved { scope, name } => {
|
||||||
Tag::Add => self.visit_add_expr(ast, idx),
|
self.visit_type_decl_ref_unresolved_impl(ast, idx, scope, name)
|
||||||
Tag::Sub => self.visit_sub_expr(ast, idx),
|
}
|
||||||
Tag::Mul => self.visit_mul_expr(ast, idx),
|
AstNode::PointerType { ty, flags } => self.visit_pointer_type_impl(ast, idx, ty, flags),
|
||||||
Tag::Div => self.visit_div_expr(ast, idx),
|
AstNode::ArrayType { length, pointer } => {
|
||||||
Tag::Rem => self.visit_rem_expr(ast, idx),
|
self.visit_array_type_impl(ast, idx, length, pointer)
|
||||||
Tag::Assign => self.visit_assign(ast, idx),
|
}
|
||||||
Tag::SubscriptExpr => self.visit_subscript_expr(ast, idx),
|
AstNode::CallExpr {
|
||||||
Tag::IfExpr => self.visit_if_expr(ast, idx),
|
func,
|
||||||
Tag::IfElseExpr => self.visit_if_else_expr(ast, idx),
|
argument_list,
|
||||||
Tag::PlaceToValueConversion => self.visit_place_to_value_conversion(ast, idx),
|
} => self.visit_call_expr_impl(ast, idx, func, argument_list),
|
||||||
Tag::ValueToPlaceConversion => self.visit_value_to_place_conversion(ast, idx),
|
AstNode::FieldAccess { field_name, expr } => {
|
||||||
Tag::Error => todo!(),
|
self.visit_field_access_impl(ast, idx, field_name, expr)
|
||||||
Tag::Undefined => todo!(),
|
}
|
||||||
Tag::Root => todo!(),
|
AstNode::ArgumentList { arguments } => {
|
||||||
Tag::File => todo!(),
|
self.visit_argument_list_impl(ast, idx, arguments)
|
||||||
|
}
|
||||||
|
AstNode::Argument { expr, name } => self.visit_argument_impl(ast, idx, expr, name),
|
||||||
|
AstNode::ExplicitCast { expr, ty } => self.visit_explicit_cast_impl(ast, idx, expr, ty),
|
||||||
|
AstNode::Deref { expr } => self.visit_deref_impl(ast, idx, expr),
|
||||||
|
AstNode::AddressOf { expr } => self.visit_address_of_impl(ast, idx, expr),
|
||||||
|
AstNode::Not { expr } => self.visit_not_impl(ast, idx, expr),
|
||||||
|
AstNode::Negate { expr } => self.visit_negate_impl(ast, idx, expr),
|
||||||
|
AstNode::PlaceToValueConversion { expr } => {
|
||||||
|
self.visit_place_to_value_conversion_impl(ast, idx, expr)
|
||||||
|
}
|
||||||
|
AstNode::ValueToPlaceConversion { expr } => {
|
||||||
|
self.visit_value_to_place_conversion_impl(ast, idx, expr)
|
||||||
|
}
|
||||||
|
AstNode::Or { lhs, rhs } => self.visit_or_impl(ast, idx, lhs, rhs),
|
||||||
|
AstNode::And { lhs, rhs } => self.visit_and_impl(ast, idx, lhs, rhs),
|
||||||
|
AstNode::BitOr { lhs, rhs } => self.visit_bit_or_impl(ast, idx, lhs, rhs),
|
||||||
|
AstNode::BitXOr { lhs, rhs } => self.visit_bit_x_or_impl(ast, idx, lhs, rhs),
|
||||||
|
AstNode::BitAnd { lhs, rhs } => self.visit_bit_and_impl(ast, idx, lhs, rhs),
|
||||||
|
AstNode::Eq { lhs, rhs } => self.visit_eq_impl(ast, idx, lhs, rhs),
|
||||||
|
AstNode::NEq { lhs, rhs } => self.visit_n_eq_impl(ast, idx, lhs, rhs),
|
||||||
|
AstNode::Lt { lhs, rhs } => self.visit_lt_impl(ast, idx, lhs, rhs),
|
||||||
|
AstNode::Gt { lhs, rhs } => self.visit_gt_impl(ast, idx, lhs, rhs),
|
||||||
|
AstNode::Le { lhs, rhs } => self.visit_le_impl(ast, idx, lhs, rhs),
|
||||||
|
AstNode::Ge { lhs, rhs } => self.visit_ge_impl(ast, idx, lhs, rhs),
|
||||||
|
AstNode::Shl { lhs, rhs } => self.visit_shl_impl(ast, idx, lhs, rhs),
|
||||||
|
AstNode::Shr { lhs, rhs } => self.visit_shr_impl(ast, idx, lhs, rhs),
|
||||||
|
AstNode::Add { lhs, rhs } => self.visit_add_impl(ast, idx, lhs, rhs),
|
||||||
|
AstNode::Sub { lhs, rhs } => self.visit_sub_impl(ast, idx, lhs, rhs),
|
||||||
|
AstNode::Mul { lhs, rhs } => self.visit_mul_impl(ast, idx, lhs, rhs),
|
||||||
|
AstNode::Div { lhs, rhs } => self.visit_div_impl(ast, idx, lhs, rhs),
|
||||||
|
AstNode::Rem { lhs, rhs } => self.visit_rem_impl(ast, idx, lhs, rhs),
|
||||||
|
AstNode::Assign { lhs, rhs } => self.visit_assign_impl(ast, idx, lhs, rhs),
|
||||||
|
AstNode::SubscriptExpr { lhs, index: rhs } => {
|
||||||
|
self.visit_subscript_expr_impl(ast, idx, lhs, rhs)
|
||||||
|
}
|
||||||
|
AstNode::IfExpr { cond, body } => self.visit_if_expr_impl(ast, idx, cond, body),
|
||||||
|
AstNode::IfElseExpr { cond, a, b } => {
|
||||||
|
self.visit_if_else_expr_impl(ast, idx, cond, a, b)
|
||||||
|
}
|
||||||
|
AstNode::Error { err } => self.visit_error_impl(ast, idx, err),
|
||||||
|
AstNode::Undefined => self.visit_undefined_impl(ast, idx),
|
||||||
|
AstNode::Root { .. } => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue