Compare commits
No commits in common. "aeab786fe3bfb652db9a2e86b8352b081fb0e1a7" and "f30b7827b8fa787ac3e8821a7d7926f8b82b918c" have entirely different histories.
aeab786fe3
...
f30b7827b8
|
@ -12,7 +12,6 @@ log = "0.4.22"
|
||||||
num-bigint = "0.4.6"
|
num-bigint = "0.4.6"
|
||||||
num-traits = "0.2.19"
|
num-traits = "0.2.19"
|
||||||
ordered-float = "4.2.2"
|
ordered-float = "4.2.2"
|
||||||
paste = "1.0.15"
|
|
||||||
petgraph = "0.6.5"
|
petgraph = "0.6.5"
|
||||||
thiserror = "1.0.63"
|
thiserror = "1.0.63"
|
||||||
unicode-xid = "0.2.4"
|
unicode-xid = "0.2.4"
|
||||||
|
|
|
@ -1,159 +0,0 @@
|
||||||
use std::fmt::Display;
|
|
||||||
|
|
||||||
use crate::{lexer::SourceLocation, writeln_indented};
|
|
||||||
|
|
||||||
use super::{
|
|
||||||
intern::{self, InternPoolWrapper as InternPool},
|
|
||||||
visitor::AstVisitorTrait,
|
|
||||||
Ast, Children, ComptimeCache, Index, Tag, TypeCache,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AstRenderVisitor<'a, W: core::fmt::Write> {
|
|
||||||
syms: &'a crate::symbol_table::syms2::Symbols,
|
|
||||||
ip: &'a InternPool,
|
|
||||||
cache: TypeCache,
|
|
||||||
comptime_cache: ComptimeCache,
|
|
||||||
scopes: Vec<Index>,
|
|
||||||
w: &'a mut W,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, W: core::fmt::Write> AstVisitorTrait<&'a Ast> for AstRenderVisitor<'_, W> {
|
|
||||||
type Error = core::fmt::Error;
|
|
||||||
|
|
||||||
type Value = ();
|
|
||||||
|
|
||||||
const UNIMPL: Self::Error = core::fmt::Error;
|
|
||||||
|
|
||||||
fn visit_any(&mut self, ast: &'a Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
|
||||||
let display = NodeDisplay::new(ast, self.ip, idx).with_indent(self.scopes.len() as u32 * 2);
|
|
||||||
|
|
||||||
match display.tag {
|
|
||||||
Tag::File
|
|
||||||
| Tag::FunctionDecl
|
|
||||||
| Tag::GlobalDecl
|
|
||||||
| Tag::Block
|
|
||||||
| Tag::BlockTrailingExpr => {
|
|
||||||
self.scopes.push(idx);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
write!(self.w, "{display}")?;
|
|
||||||
|
|
||||||
for child in display.children.0 {
|
|
||||||
self.visit_any(ast, child)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
match display.tag {
|
|
||||||
Tag::File
|
|
||||||
| Tag::FunctionDecl
|
|
||||||
| Tag::GlobalDecl
|
|
||||||
| Tag::Block
|
|
||||||
| Tag::BlockTrailingExpr => {
|
|
||||||
self.scopes.pop();
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct AstRenderer<'a> {
|
|
||||||
ast: &'a Ast,
|
|
||||||
#[allow(dead_code)]
|
|
||||||
syms: &'a crate::symbol_table::syms2::Symbols,
|
|
||||||
ip: &'a InternPool,
|
|
||||||
cache: TypeCache,
|
|
||||||
comptime_cache: ComptimeCache,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct NodeDisplay {
|
|
||||||
node: Index,
|
|
||||||
tag: Tag,
|
|
||||||
loc: SourceLocation,
|
|
||||||
children: Children,
|
|
||||||
is_comptime: bool,
|
|
||||||
ty: intern::Index,
|
|
||||||
indent: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NodeDisplay {
|
|
||||||
pub fn new(ast: &Ast, ip: &InternPool, node: Index) -> NodeDisplay {
|
|
||||||
let tag = ast.tags[node];
|
|
||||||
let loc = ast.source_locs[node];
|
|
||||||
|
|
||||||
let children = Children(ast.get_node_children(node));
|
|
||||||
let ty = ast.get_type_of_node(ip, &mut TypeCache::new(), node);
|
|
||||||
|
|
||||||
let is_comptime = ast.is_node_comptime_evaluable(&mut ComptimeCache::default(), node);
|
|
||||||
|
|
||||||
Self {
|
|
||||||
node,
|
|
||||||
tag,
|
|
||||||
loc,
|
|
||||||
children,
|
|
||||||
is_comptime,
|
|
||||||
ty,
|
|
||||||
indent: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn with_indent(self, indent: u32) -> Self {
|
|
||||||
Self { indent, ..self }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for NodeDisplay {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
let Self {
|
|
||||||
node,
|
|
||||||
tag,
|
|
||||||
loc,
|
|
||||||
children,
|
|
||||||
is_comptime,
|
|
||||||
ty,
|
|
||||||
indent,
|
|
||||||
} = self;
|
|
||||||
writeln_indented!(
|
|
||||||
*indent,
|
|
||||||
f,
|
|
||||||
"{node} {}({ty}) = ({loc}) {tag:?} {children}",
|
|
||||||
if *is_comptime { "CONST " } else { "" }
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> AstRenderer<'a> {
|
|
||||||
pub fn new(
|
|
||||||
ast: &'a Ast,
|
|
||||||
ip: &'a InternPool,
|
|
||||||
syms: &'a crate::symbol_table::syms2::Symbols,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
ast,
|
|
||||||
syms,
|
|
||||||
ip,
|
|
||||||
cache: TypeCache::new(),
|
|
||||||
comptime_cache: ComptimeCache::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn render<W: core::fmt::Write>(&mut self, w: &mut W) -> core::fmt::Result {
|
|
||||||
let mut visitor = AstRenderVisitor {
|
|
||||||
syms: self.syms,
|
|
||||||
ip: self.ip,
|
|
||||||
cache: TypeCache::new(),
|
|
||||||
comptime_cache: ComptimeCache::default(),
|
|
||||||
scopes: Vec::new(),
|
|
||||||
w,
|
|
||||||
};
|
|
||||||
|
|
||||||
for idx in self.ast.get_root_file_indices() {
|
|
||||||
visitor.visit_any(self.ast, idx)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1382,13 +1382,6 @@ impl InternPool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn try_get_return_type(&self, func: Index) -> Option<Index> {
|
|
||||||
match self.get_key(func) {
|
|
||||||
Key::FunctionType { return_type, .. } => Some(return_type),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_pointer_type(&mut self, pointee: Index, flags: Option<PointerFlags>) -> Index {
|
pub fn get_pointer_type(&mut self, pointee: Index, flags: Option<PointerFlags>) -> Index {
|
||||||
let key = Key::PointerType {
|
let key = Key::PointerType {
|
||||||
pointee,
|
pointee,
|
||||||
|
|
924
src/ast2/ir.rs
924
src/ast2/ir.rs
File diff suppressed because it is too large
Load diff
175
src/ast2/mod.rs
175
src/ast2/mod.rs
|
@ -10,15 +10,12 @@ use num_bigint::BigInt;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::FloatingType, comptime::ComptimeNumber, lexer::SourceLocation,
|
ast::FloatingType, comptime::ComptimeNumber, lexer::SourceLocation,
|
||||||
symbol_table::syms2::DeclKind, tokens::Token,
|
symbol_table::syms2::DeclKind, tokens::Token, writeln_indented,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod debug;
|
|
||||||
pub mod intern;
|
pub mod intern;
|
||||||
pub mod ir;
|
pub mod ir;
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
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)]
|
||||||
|
@ -29,8 +26,6 @@ pub enum Tag {
|
||||||
File,
|
File,
|
||||||
/// `data` is an intern to a name, and an index into extra of [index: return_type, index: ParameterList]
|
/// `data` is an intern to a name, and an index into extra of [index: return_type, index: ParameterList]
|
||||||
FunctionProto,
|
FunctionProto,
|
||||||
/// `data` is an intern to a name, and an intern to the function type
|
|
||||||
FunctionProtoInterned,
|
|
||||||
/// `data` is an index to a FunctionProto and an index to a Block
|
/// `data` is an index to a FunctionProto and an index to a Block
|
||||||
FunctionDecl,
|
FunctionDecl,
|
||||||
/// `data` is a range from a..b into extra of indices to parameters
|
/// `data` is a range from a..b into extra of indices to parameters
|
||||||
|
@ -61,11 +56,9 @@ pub enum Tag {
|
||||||
GlobalDecl,
|
GlobalDecl,
|
||||||
/// `data` is an intern to a name, and an offset into extra of `[flags, type0 ,..., typeN ,name0 ,..., nameN]`
|
/// `data` is an intern to a name, and an offset into extra of `[flags, type0 ,..., typeN ,name0 ,..., nameN]`
|
||||||
StructDecl,
|
StructDecl,
|
||||||
/// `data` is an intern to a name, and an intern to the type of the struct
|
|
||||||
StructDeclInterned,
|
|
||||||
/// `data` is an index to a type, and an intern to a name
|
/// `data` is an index to a type, and an intern to a name
|
||||||
FieldDecl,
|
FieldDecl,
|
||||||
/// `data` is an index to a Parameter, VarDecl, GlobalDecl or FunctionDecl, and an opaque DeclKind
|
/// `data` is an index to a VarDecl, GlobalDecl or FunctionDecl, and an opaque DeclKind
|
||||||
DeclRef,
|
DeclRef,
|
||||||
/// `data` is an inlined key into the symbol table (scope: index, name: intern)
|
/// `data` is an inlined key into the symbol table (scope: index, name: intern)
|
||||||
DeclRefUnresolved,
|
DeclRefUnresolved,
|
||||||
|
@ -137,7 +130,6 @@ impl Tag {
|
||||||
| Tag::PointerType
|
| Tag::PointerType
|
||||||
| Tag::InternedType
|
| Tag::InternedType
|
||||||
| Tag::ArrayType
|
| Tag::ArrayType
|
||||||
| Tag::StructDeclInterned
|
|
||||||
| Tag::StructDecl => true,
|
| Tag::StructDecl => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
@ -172,8 +164,6 @@ impl Tag {
|
||||||
| Tag::SubscriptExpr
|
| Tag::SubscriptExpr
|
||||||
| Tag::IfExpr
|
| Tag::IfExpr
|
||||||
| Tag::IfElseExpr
|
| Tag::IfElseExpr
|
||||||
| Tag::PlaceToValueConversion
|
|
||||||
| Tag::ValueToPlaceConversion
|
|
||||||
| Tag::Block
|
| Tag::Block
|
||||||
| &Tag::BlockTrailingExpr => true,
|
| &Tag::BlockTrailingExpr => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
|
@ -182,7 +172,7 @@ impl Tag {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, thiserror::Error, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, thiserror::Error, PartialEq, Eq)]
|
||||||
pub enum ParseError {
|
enum ParseError {
|
||||||
#[error("Unexpected end of token iter.")]
|
#[error("Unexpected end of token iter.")]
|
||||||
UnexpectedEndOfTokens,
|
UnexpectedEndOfTokens,
|
||||||
#[error("Expected Token {0}.")]
|
#[error("Expected Token {0}.")]
|
||||||
|
@ -377,7 +367,6 @@ impl From<(Tag, Data)> for ExpandedData {
|
||||||
| Tag::CallExpr
|
| Tag::CallExpr
|
||||||
| Tag::ArrayType
|
| Tag::ArrayType
|
||||||
| Tag::FunctionDecl => Self::from_two_indices(data),
|
| Tag::FunctionDecl => Self::from_two_indices(data),
|
||||||
Tag::StructDeclInterned | Tag::FunctionProtoInterned => Self::from_two_interns(data),
|
|
||||||
Tag::ReturnExprStmt
|
Tag::ReturnExprStmt
|
||||||
| Tag::DeclRef
|
| Tag::DeclRef
|
||||||
| Tag::TypeDeclRef
|
| Tag::TypeDeclRef
|
||||||
|
@ -499,7 +488,7 @@ impl Data {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub enum PlaceOrValue {
|
enum PlaceOrValue {
|
||||||
Value(index::Index),
|
Value(index::Index),
|
||||||
Place(index::Index),
|
Place(index::Index),
|
||||||
}
|
}
|
||||||
|
@ -532,24 +521,6 @@ impl PlaceOrValue {
|
||||||
PlaceOrValue::Place(_) => Self::Place(index),
|
PlaceOrValue::Place(_) => Self::Place(index),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn map_value<F>(self, f: F) -> Self
|
|
||||||
where
|
|
||||||
F: FnOnce(Index) -> Self,
|
|
||||||
{
|
|
||||||
match self {
|
|
||||||
PlaceOrValue::Value(index) => f(index),
|
|
||||||
_ => self,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn map_place<F>(self, f: F) -> Self
|
|
||||||
where
|
|
||||||
F: FnOnce(Index) -> Self,
|
|
||||||
{
|
|
||||||
match self {
|
|
||||||
PlaceOrValue::Place(index) => f(index),
|
|
||||||
_ => self,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<index::Index> for PlaceOrValue {
|
impl From<index::Index> for PlaceOrValue {
|
||||||
|
@ -620,14 +591,6 @@ mod index {
|
||||||
|
|
||||||
inner.map(Self)
|
inner.map(Self)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_slice(slice: &[u32]) -> &[Option<Self>] {
|
|
||||||
unsafe { core::mem::transmute(slice) }
|
|
||||||
}
|
|
||||||
pub unsafe fn from_slice_unchecked(slice: &[u32]) -> &[Self] {
|
|
||||||
unsafe { core::mem::transmute(slice) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn kind(&self) -> Kind {
|
pub fn kind(&self) -> Kind {
|
||||||
Kind::try_from(((self.0.get() >> 28) & 0b1111) as u8).unwrap()
|
Kind::try_from(((self.0.get() >> 28) & 0b1111) as u8).unwrap()
|
||||||
}
|
}
|
||||||
|
@ -1061,37 +1024,21 @@ impl Ast {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// converts from a place expression to a value expression.
|
/// converts from a place expression to a value expression.
|
||||||
fn push_place_to_value_conversion(&mut self, index: Index) -> PlaceOrValue {
|
fn push_place_to_value_conversion(&mut self, index: Index) -> Index {
|
||||||
let loc = self.get_loc(index);
|
let loc = self.get_loc(index);
|
||||||
let i = self.reserve_node_other();
|
let i = self.reserve_node_other();
|
||||||
self.set_tag_data_source_loc(i, Tag::PlaceToValueConversion, Data::index(index), loc);
|
self.set_tag_data_source_loc(i, Tag::PlaceToValueConversion, Data::index(index), loc);
|
||||||
|
|
||||||
PlaceOrValue::Value(i)
|
i
|
||||||
}
|
}
|
||||||
|
|
||||||
/// converts from a value expression to a place expression.
|
/// converts from a value expression to a place expression.
|
||||||
fn push_value_to_place_conversion(&mut self, index: Index) -> PlaceOrValue {
|
fn push_value_to_place_conversion(&mut self, index: Index) -> Index {
|
||||||
let loc = self.get_loc(index);
|
let loc = self.get_loc(index);
|
||||||
let i = self.reserve_node_other();
|
let i = self.reserve_node_other();
|
||||||
self.set_tag_data_source_loc(i, Tag::ValueToPlaceConversion, Data::index(index), loc);
|
self.set_tag_data_source_loc(i, Tag::ValueToPlaceConversion, Data::index(index), loc);
|
||||||
|
|
||||||
PlaceOrValue::Place(i)
|
i
|
||||||
}
|
|
||||||
|
|
||||||
/// converts the expression to a value expression, if it isn't one already.
|
|
||||||
fn convert_to_value_expr(&mut self, lrvalue: PlaceOrValue) -> Index {
|
|
||||||
match lrvalue {
|
|
||||||
PlaceOrValue::Value(index) => index,
|
|
||||||
PlaceOrValue::Place(index) => self.push_place_to_value_conversion(index).into_index(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// converts the expression to a place expression, if it isn't one already.
|
|
||||||
fn convert_to_place_expr(&mut self, lrvalue: PlaceOrValue) -> Index {
|
|
||||||
match lrvalue {
|
|
||||||
PlaceOrValue::Place(index) => index,
|
|
||||||
PlaceOrValue::Value(index) => self.push_value_to_place_conversion(index).into_index(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_binary(&mut self, tag: Tag, lhs: Index, rhs: Index, loc: SourceLocation) -> Index {
|
fn push_binary(&mut self, tag: Tag, lhs: Index, rhs: Index, loc: SourceLocation) -> Index {
|
||||||
|
@ -1425,11 +1372,6 @@ impl Ast {
|
||||||
|
|
||||||
ip.as_mut().get_function_type(return_type, parameters)
|
ip.as_mut().get_function_type(return_type, parameters)
|
||||||
}
|
}
|
||||||
Tag::FunctionProtoInterned | Tag::StructDeclInterned => {
|
|
||||||
let (_, ty) = data.as_two_interns();
|
|
||||||
|
|
||||||
ty
|
|
||||||
}
|
|
||||||
Tag::BlockTrailingExpr => {
|
Tag::BlockTrailingExpr => {
|
||||||
let (_a, b) = data.as_extra_range();
|
let (_a, b) = data.as_extra_range();
|
||||||
self.get_type_of_node(ip, cache, Index::from_u32(self.extra[b - 1]).unwrap())
|
self.get_type_of_node(ip, cache, Index::from_u32(self.extra[b - 1]).unwrap())
|
||||||
|
@ -1506,7 +1448,6 @@ impl Ast {
|
||||||
// TODO: find out of the expression is const, volatile for flags
|
// TODO: find out of the expression is const, volatile for flags
|
||||||
|
|
||||||
// ip.try_get_pointer_type(ty, None).unwrap()
|
// ip.try_get_pointer_type(ty, None).unwrap()
|
||||||
|
|
||||||
// note: because of value-to-place and place-to-value,
|
// note: because of value-to-place and place-to-value,
|
||||||
// this is actually the same type.
|
// this is actually the same type.
|
||||||
ty
|
ty
|
||||||
|
@ -1601,9 +1542,6 @@ impl Ast {
|
||||||
.map(|&i| Index::from_u32(i).unwrap())
|
.map(|&i| Index::from_u32(i).unwrap())
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
Tag::FunctionProtoInterned => {
|
|
||||||
vec![]
|
|
||||||
}
|
|
||||||
Tag::FunctionDecl => {
|
Tag::FunctionDecl => {
|
||||||
let (a, b) = data.as_two_indices();
|
let (a, b) = data.as_two_indices();
|
||||||
vec![a, b]
|
vec![a, b]
|
||||||
|
@ -1703,7 +1641,6 @@ impl Ast {
|
||||||
let (a, _) = data.as_index_and_extra_offset();
|
let (a, _) = data.as_index_and_extra_offset();
|
||||||
vec![a]
|
vec![a]
|
||||||
}
|
}
|
||||||
Tag::StructDeclInterned => vec![],
|
|
||||||
Tag::StructDecl => {
|
Tag::StructDecl => {
|
||||||
let (_a, offset) = data.as_intern_and_extra_offset();
|
let (_a, offset) = data.as_intern_and_extra_offset();
|
||||||
let flags = StructFlags::unpack(self.extra[offset]);
|
let flags = StructFlags::unpack(self.extra[offset]);
|
||||||
|
@ -1751,16 +1688,15 @@ impl Ast {
|
||||||
let is_comptime = match tag {
|
let is_comptime = match tag {
|
||||||
Tag::Parameter => false,
|
Tag::Parameter => false,
|
||||||
// TODO: figure out if there are function protos that arent const
|
// TODO: figure out if there are function protos that arent const
|
||||||
Tag::FunctionProto | Tag::FunctionProtoInterned| Tag::FunctionDecl | Tag::Block | Tag::BlockTrailingExpr => {
|
// Tag::FunctionProto | Tag::FunctionDecl | Tag::Block | Tag::BlockTrailingExpr => {
|
||||||
//are_children_comptime(self, cache)
|
// are_children_comptime(self, cache)
|
||||||
false
|
// }
|
||||||
}
|
|
||||||
Tag::Constant => true,
|
Tag::Constant => true,
|
||||||
Tag::ReturnStmt => true,
|
Tag::ReturnStmt => true,
|
||||||
Tag::ReturnExprStmt => are_children_comptime(self, cache),
|
Tag::ReturnExprStmt => are_children_comptime(self, cache),
|
||||||
Tag::MutVarDecl | Tag::MutVarDeclAssignment => false,
|
Tag::MutVarDecl | Tag::MutVarDeclAssignment => false,
|
||||||
Tag::VarDecl => false,
|
// Tag::VarDecl => true,
|
||||||
Tag::ValueToPlaceConversion => false,
|
// Tag::ValueToPlaceConversion => false,
|
||||||
Tag::PlaceToValueConversion | Tag::VarDeclAssignment => {
|
Tag::PlaceToValueConversion | Tag::VarDeclAssignment => {
|
||||||
are_children_comptime(self, cache)
|
are_children_comptime(self, cache)
|
||||||
}
|
}
|
||||||
|
@ -1769,13 +1705,12 @@ impl Ast {
|
||||||
Tag::FieldDecl => true,
|
Tag::FieldDecl => true,
|
||||||
Tag::DeclRef => self.tags[data.as_index()] == Tag::GlobalDecl,
|
Tag::DeclRef => self.tags[data.as_index()] == Tag::GlobalDecl,
|
||||||
Tag::InternedType | Tag::PointerType | Tag::ArrayType | Tag::TypeDeclRef => true,
|
Tag::InternedType | Tag::PointerType | Tag::ArrayType | Tag::TypeDeclRef => true,
|
||||||
Tag::CallExpr => false, // are_children_comptime(self, cache),
|
// Tag::CallExpr => are_children_comptime(self, cache),
|
||||||
Tag::FieldAccess => {
|
// Tag::FieldAccess => {
|
||||||
// let parent = data.as_index_intern().0;
|
// let parent = data.as_index_intern().0;
|
||||||
// cache.mark_as_dominated_by(index, parent);
|
// cache.mark_as_dominated_by(index, parent);
|
||||||
// self.is_node_comptime_evaluable(cache, parent)
|
// self.is_node_comptime_evaluable(cache, parent)
|
||||||
false
|
// }
|
||||||
}
|
|
||||||
Tag::ArgumentList => are_children_comptime(self, cache),
|
Tag::ArgumentList => are_children_comptime(self, cache),
|
||||||
Tag::Argument => self.is_node_comptime_evaluable(cache, data.as_index()),
|
Tag::Argument => self.is_node_comptime_evaluable(cache, data.as_index()),
|
||||||
Tag::NamedArgument => {
|
Tag::NamedArgument => {
|
||||||
|
@ -1804,14 +1739,14 @@ impl Ast {
|
||||||
| Tag::Sub
|
| Tag::Sub
|
||||||
| Tag::Mul
|
| Tag::Mul
|
||||||
| Tag::Div
|
| Tag::Div
|
||||||
| Tag::SubscriptExpr // TODO: add array decl expression
|
| Tag::SubscriptExpr // TODO: add array decl expression
|
||||||
| Tag::Rem => are_children_comptime(self, cache),
|
| Tag::Rem => are_children_comptime(self, cache),
|
||||||
Tag::Assign => {
|
Tag::Assign => {
|
||||||
let (left, _) = data.as_two_indices();
|
let (left, _) = data.as_two_indices();
|
||||||
cache.mark_as_dominated_by(index, left);
|
cache.mark_as_dominated_by(index, left);
|
||||||
are_children_comptime(self, cache)
|
are_children_comptime(self, cache)
|
||||||
}
|
}
|
||||||
Tag::IfExpr | Tag::IfElseExpr => false, // are_children_comptime(self, cache),
|
// Tag::IfExpr | Tag::IfElseExpr => are_children_comptime(self, cache),
|
||||||
Tag::Root
|
Tag::Root
|
||||||
| Tag::File
|
| Tag::File
|
||||||
| Tag::ParameterList
|
| Tag::ParameterList
|
||||||
|
@ -2257,3 +2192,75 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct AstRenderer<'a> {
|
||||||
|
ast: &'a Ast,
|
||||||
|
#[allow(dead_code)]
|
||||||
|
syms: &'a crate::symbol_table::syms2::Symbols,
|
||||||
|
ip: &'a InternPool,
|
||||||
|
cache: TypeCache,
|
||||||
|
comptime_cache: ComptimeCache,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct NodeDisplay<'a> {
|
||||||
|
node: Index,
|
||||||
|
ast: &'a Ast,
|
||||||
|
ip: &'a InternPool,
|
||||||
|
}
|
||||||
|
impl<'a> Display for NodeDisplay<'a> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let node = self.node;
|
||||||
|
let tag = self.ast.tags[node];
|
||||||
|
let loc = self.ast.source_locs[node];
|
||||||
|
|
||||||
|
let children = Children(self.ast.get_node_children(node));
|
||||||
|
let ty = self
|
||||||
|
.ast
|
||||||
|
.get_type_of_node(self.ip, &mut TypeCache::new(), node);
|
||||||
|
|
||||||
|
let is_comptime = self
|
||||||
|
.ast
|
||||||
|
.is_node_comptime_evaluable(&mut ComptimeCache::default(), node);
|
||||||
|
writeln!(
|
||||||
|
f,
|
||||||
|
"{node} {}({ty}) = ({loc}) {tag:?} {children}",
|
||||||
|
if is_comptime { "CONST " } else { "" }
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> AstRenderer<'a> {
|
||||||
|
pub fn new(
|
||||||
|
ast: &'a Ast,
|
||||||
|
ip: &'a InternPool,
|
||||||
|
syms: &'a crate::symbol_table::syms2::Symbols,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
ast,
|
||||||
|
syms,
|
||||||
|
ip,
|
||||||
|
cache: TypeCache::new(),
|
||||||
|
comptime_cache: ComptimeCache::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render<W: core::fmt::Write>(&mut self, w: &mut W) -> core::fmt::Result {
|
||||||
|
self.ast.visitor().visit_pre(|ast, scopes, node, tag, _| {
|
||||||
|
let loc = ast.source_locs[node];
|
||||||
|
|
||||||
|
let children = Children(ast.get_node_children(node));
|
||||||
|
let ty = self.ast.get_type_of_node(self.ip, &mut self.cache, node);
|
||||||
|
let is_comptime = ast.is_node_comptime_evaluable(&mut self.comptime_cache, node);
|
||||||
|
_ = writeln_indented!(
|
||||||
|
scopes.len() as u32 * 2,
|
||||||
|
w,
|
||||||
|
"{node} {}({ty}) = ({loc}) {tag:?} {children}",
|
||||||
|
if is_comptime { "CONST " } else { "" }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -47,12 +47,16 @@ impl Parser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn display(&self) -> debug::AstRenderer<'_> {
|
pub fn display(&self) -> AstRenderer<'_> {
|
||||||
debug::AstRenderer::new(&self.ast, &self.intern, &self.syms)
|
AstRenderer::new(&self.ast, &self.intern, &self.syms)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn node_display(&self, node: Index) -> debug::NodeDisplay {
|
pub fn node_display(&self, node: Index) -> NodeDisplay<'_> {
|
||||||
debug::NodeDisplay::new(&self.ast, &self.intern, node)
|
NodeDisplay {
|
||||||
|
node,
|
||||||
|
ast: &self.ast,
|
||||||
|
ip: &self.intern,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_comptime_folding_graph(&mut self, pointer_bits: u16) {
|
pub fn create_comptime_folding_graph(&mut self, pointer_bits: u16) {
|
||||||
|
@ -149,7 +153,6 @@ impl Parser {
|
||||||
/// folds more AST-patterns into structures that are easier to build the IR with
|
/// folds more AST-patterns into structures that are easier to build the IR with
|
||||||
pub fn fold_more_patterns(&mut self) {
|
pub fn fold_more_patterns(&mut self) {
|
||||||
use visitor::AstExt;
|
use visitor::AstExt;
|
||||||
|
|
||||||
self.ast.visitor_mut().visit_post(|ast, _, _i, tag, data| {
|
self.ast.visitor_mut().visit_post(|ast, _, _i, tag, data| {
|
||||||
match tag {
|
match tag {
|
||||||
// normalise functions with block-with-trailing-expr into block
|
// normalise functions with block-with-trailing-expr into block
|
||||||
|
@ -1167,12 +1170,18 @@ impl Parser {
|
||||||
|
|
||||||
/// converts the expression to a value expression, if it isn't one already.
|
/// converts the expression to a value expression, if it isn't one already.
|
||||||
fn convert_to_value_expr(&mut self, lrvalue: PlaceOrValue) -> Index {
|
fn convert_to_value_expr(&mut self, lrvalue: PlaceOrValue) -> Index {
|
||||||
self.ast.convert_to_value_expr(lrvalue)
|
match lrvalue {
|
||||||
|
PlaceOrValue::Value(index) => index,
|
||||||
|
PlaceOrValue::Place(index) => self.ast.push_place_to_value_conversion(index),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// converts the expression to a place expression, if it isn't one already.
|
/// converts the expression to a place expression, if it isn't one already.
|
||||||
fn convert_to_place_expr(&mut self, lrvalue: PlaceOrValue) -> Index {
|
fn convert_to_place_expr(&mut self, lrvalue: PlaceOrValue) -> Index {
|
||||||
self.ast.convert_to_place_expr(lrvalue)
|
match lrvalue {
|
||||||
|
PlaceOrValue::Place(index) => index,
|
||||||
|
PlaceOrValue::Value(index) => self.ast.push_value_to_place_conversion(index),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// PREFIX_EXPR <-
|
/// PREFIX_EXPR <-
|
||||||
|
|
631
src/ast2/tag.rs
631
src/ast2/tag.rs
|
@ -1,631 +0,0 @@
|
||||||
use super::{
|
|
||||||
intern::{Index as Interned, PointerFlags, StructFlags},
|
|
||||||
visitor::AstExt,
|
|
||||||
Ast, Index, ParseError, Tag,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub trait AstNodeExt {
|
|
||||||
fn get_ast_node(&self, idx: Index) -> AstNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AstNodeExt for &mut Ast {
|
|
||||||
fn get_ast_node(&self, idx: Index) -> AstNode {
|
|
||||||
<Ast as AstNodeExt>::get_ast_node(self, idx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AstNodeExt for &Ast {
|
|
||||||
fn get_ast_node(&self, idx: Index) -> AstNode {
|
|
||||||
<Ast as AstNodeExt>::get_ast_node(self, idx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AstNodeExt for Ast {
|
|
||||||
fn get_ast_node(&self, idx: Index) -> AstNode {
|
|
||||||
let (tag, data) = self.get_node_tag_and_data(idx);
|
|
||||||
|
|
||||||
match tag {
|
|
||||||
Tag::Root => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
Tag::File => {
|
|
||||||
let (a, b) = data.as_extra_range();
|
|
||||||
let decls = unsafe { Index::from_slice_unchecked(&self.extra[a..b]).to_vec() };
|
|
||||||
|
|
||||||
AstNode::File { decls }
|
|
||||||
}
|
|
||||||
Tag::FunctionProto => {
|
|
||||||
let (name, extra) = data.as_intern_and_extra_offset();
|
|
||||||
|
|
||||||
let (return_type, parameter_list) = (
|
|
||||||
Index::from_u32(self.extra[extra]).unwrap(),
|
|
||||||
Index::from_u32(self.extra[extra + 1]).unwrap(),
|
|
||||||
);
|
|
||||||
|
|
||||||
AstNode::FunctionProto {
|
|
||||||
name,
|
|
||||||
return_type,
|
|
||||||
parameter_list,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Tag::FunctionProtoInterned => {
|
|
||||||
let (name, ty) = data.as_two_interns();
|
|
||||||
AstNode::FunctionProtoInterned { name, ty }
|
|
||||||
}
|
|
||||||
Tag::FunctionDecl => {
|
|
||||||
let (proto, body) = data.as_two_indices();
|
|
||||||
|
|
||||||
AstNode::FunctionDecl { proto, body }
|
|
||||||
}
|
|
||||||
Tag::ParameterList => {
|
|
||||||
let (a, b) = data.as_extra_range();
|
|
||||||
let params = unsafe { Index::from_slice_unchecked(&self.extra[a..b]).to_vec() };
|
|
||||||
|
|
||||||
AstNode::ParameterList { params }
|
|
||||||
}
|
|
||||||
Tag::Parameter => {
|
|
||||||
let (ty, name) = data.as_index_intern();
|
|
||||||
|
|
||||||
AstNode::Parameter { ty, name }
|
|
||||||
}
|
|
||||||
Tag::Block => {
|
|
||||||
let (a, b) = data.as_extra_range();
|
|
||||||
let statements = unsafe { Index::from_slice_unchecked(&self.extra[a..b]).to_vec() };
|
|
||||||
|
|
||||||
AstNode::Block {
|
|
||||||
statements,
|
|
||||||
expr: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Tag::BlockTrailingExpr => {
|
|
||||||
let (a, b) = data.as_extra_range();
|
|
||||||
let (expr, statements) = unsafe {
|
|
||||||
Index::from_slice_unchecked(&self.extra[a..b])
|
|
||||||
.split_last()
|
|
||||||
.unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
AstNode::Block {
|
|
||||||
statements: statements.to_vec(),
|
|
||||||
expr: Some(*expr),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Tag::Constant => {
|
|
||||||
let (ty, value) = data.as_index_intern();
|
|
||||||
AstNode::Constant { ty, value }
|
|
||||||
}
|
|
||||||
Tag::ExprStmt => AstNode::ExprStmt {
|
|
||||||
expr: data.as_index(),
|
|
||||||
},
|
|
||||||
Tag::ReturnStmt => AstNode::ReturnStmt,
|
|
||||||
Tag::ReturnExprStmt => AstNode::ReturnExprStmt {
|
|
||||||
expr: data.as_index(),
|
|
||||||
},
|
|
||||||
Tag::VarDecl => {
|
|
||||||
let (a, _) = data.as_extra_range();
|
|
||||||
let name = Interned::from_u32(self.extra[a]);
|
|
||||||
let ty = Index::from_u32(self.extra[a + 1]).unwrap();
|
|
||||||
|
|
||||||
AstNode::VarDecl { name, ty }
|
|
||||||
}
|
|
||||||
Tag::MutVarDecl => {
|
|
||||||
let (a, _) = data.as_extra_range();
|
|
||||||
let name = Interned::from_u32(self.extra[a]);
|
|
||||||
let ty = Index::from_u32(self.extra[a + 1]).unwrap();
|
|
||||||
|
|
||||||
AstNode::MutVarDecl { name, ty }
|
|
||||||
}
|
|
||||||
Tag::VarDeclAssignment => {
|
|
||||||
let (a, b) = data.as_extra_range();
|
|
||||||
let extra = &self.extra[a..b];
|
|
||||||
let name = Interned::from_u32(*extra.get(0).unwrap());
|
|
||||||
let expr = Index::from_u32(*extra.get(1).unwrap()).unwrap();
|
|
||||||
let ty = extra.get(2).map(|&inner| Index::from_u32(inner).unwrap());
|
|
||||||
|
|
||||||
AstNode::MutVarDeclAssignment { name, expr, ty }
|
|
||||||
}
|
|
||||||
Tag::MutVarDeclAssignment => {
|
|
||||||
let (a, b) = data.as_extra_range();
|
|
||||||
let extra = &self.extra[a..b];
|
|
||||||
let name = Interned::from_u32(*extra.get(0).unwrap());
|
|
||||||
let expr = Index::from_u32(*extra.get(1).unwrap()).unwrap();
|
|
||||||
let ty = extra.get(2).map(|&inner| Index::from_u32(inner).unwrap());
|
|
||||||
|
|
||||||
AstNode::MutVarDeclAssignment { name, expr, ty }
|
|
||||||
}
|
|
||||||
Tag::GlobalDecl => {
|
|
||||||
let (name, offset) = data.as_intern_and_extra_offset();
|
|
||||||
let ty = Index::from_u32(self.extra[offset]).unwrap();
|
|
||||||
let expr = Index::from_u32(self.extra[offset + 1]).unwrap();
|
|
||||||
|
|
||||||
AstNode::GlobalDecl { name, expr, ty }
|
|
||||||
}
|
|
||||||
Tag::StructDecl => {
|
|
||||||
let (name, offset) = data.as_intern_and_extra_offset();
|
|
||||||
let flags = StructFlags::unpack(self.extra[offset]);
|
|
||||||
|
|
||||||
let types = (offset + 1)..(offset + 1 + flags.num_fields as usize);
|
|
||||||
let names = (offset + 1 + flags.num_fields as usize)
|
|
||||||
..(offset + 1 + flags.num_fields as usize * 2);
|
|
||||||
|
|
||||||
let field_types =
|
|
||||||
unsafe { Index::from_slice_unchecked(&self.extra[types]).to_vec() };
|
|
||||||
|
|
||||||
let field_names = self.extra[names]
|
|
||||||
.iter()
|
|
||||||
.map(|&i| Interned::from_u32(i))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
AstNode::StructDecl {
|
|
||||||
name,
|
|
||||||
flags,
|
|
||||||
field_names,
|
|
||||||
field_types,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Tag::StructDeclInterned => {
|
|
||||||
let (name, ty) = data.as_two_interns();
|
|
||||||
|
|
||||||
AstNode::StructDeclInterned { name, ty }
|
|
||||||
}
|
|
||||||
Tag::FieldDecl => {
|
|
||||||
let (ty, name) = data.as_index_intern();
|
|
||||||
|
|
||||||
AstNode::FieldDecl { name, ty }
|
|
||||||
}
|
|
||||||
Tag::DeclRef => AstNode::DeclRef {
|
|
||||||
decl: data.as_index(),
|
|
||||||
},
|
|
||||||
Tag::DeclRefUnresolved => {
|
|
||||||
let (scope, name) = data.as_index_intern();
|
|
||||||
AstNode::DeclRefUnresolved { scope, name }
|
|
||||||
}
|
|
||||||
Tag::InternedType => AstNode::InternedType {
|
|
||||||
intern: data.as_intern(),
|
|
||||||
},
|
|
||||||
Tag::TypeDeclRef => AstNode::TypeDeclRef {
|
|
||||||
decl: data.as_index(),
|
|
||||||
},
|
|
||||||
Tag::TypeDeclRefUnresolved => {
|
|
||||||
let (scope, name) = data.as_index_intern();
|
|
||||||
AstNode::TypeDeclRefUnresolved { scope, name }
|
|
||||||
}
|
|
||||||
Tag::PointerType => {
|
|
||||||
let (ty, flags) = data.as_index_and_opaque();
|
|
||||||
let flags = PointerFlags::unpack(flags as u8);
|
|
||||||
AstNode::PointerType { ty, flags }
|
|
||||||
}
|
|
||||||
Tag::ArrayType => {
|
|
||||||
let (length, pointer) = data.as_two_indices();
|
|
||||||
|
|
||||||
AstNode::ArrayType { length, pointer }
|
|
||||||
}
|
|
||||||
Tag::CallExpr => {
|
|
||||||
let (func, argument_list) = data.as_two_indices();
|
|
||||||
AstNode::CallExpr {
|
|
||||||
func,
|
|
||||||
argument_list,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Tag::FieldAccess => {
|
|
||||||
let (expr, field_name) = data.as_index_intern();
|
|
||||||
AstNode::FieldAccess { field_name, expr }
|
|
||||||
}
|
|
||||||
Tag::ArgumentList => {
|
|
||||||
let (a, b) = data.as_extra_range();
|
|
||||||
let arguments = unsafe { Index::from_slice_unchecked(&self.extra[a..b]).to_vec() };
|
|
||||||
|
|
||||||
AstNode::ArgumentList { arguments }
|
|
||||||
}
|
|
||||||
Tag::Argument => AstNode::Argument {
|
|
||||||
expr: data.as_index(),
|
|
||||||
name: None,
|
|
||||||
},
|
|
||||||
Tag::NamedArgument => {
|
|
||||||
let (expr, name) = data.as_index_intern();
|
|
||||||
AstNode::Argument {
|
|
||||||
expr,
|
|
||||||
name: Some(name),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Tag::ExplicitCast => {
|
|
||||||
let (expr, ty) = data.as_two_indices();
|
|
||||||
|
|
||||||
AstNode::ExplicitCast { expr, ty }
|
|
||||||
}
|
|
||||||
Tag::Deref => AstNode::Deref {
|
|
||||||
expr: data.as_index(),
|
|
||||||
},
|
|
||||||
Tag::AddressOf => AstNode::AddressOf {
|
|
||||||
expr: data.as_index(),
|
|
||||||
},
|
|
||||||
Tag::Not => AstNode::Not {
|
|
||||||
expr: data.as_index(),
|
|
||||||
},
|
|
||||||
Tag::Negate => AstNode::Negate {
|
|
||||||
expr: data.as_index(),
|
|
||||||
},
|
|
||||||
Tag::PlaceToValueConversion => AstNode::PlaceToValueConversion {
|
|
||||||
expr: data.as_index(),
|
|
||||||
},
|
|
||||||
Tag::ValueToPlaceConversion => AstNode::ValueToPlaceConversion {
|
|
||||||
expr: data.as_index(),
|
|
||||||
},
|
|
||||||
Tag::Or => {
|
|
||||||
let (lhs, rhs) = data.as_two_indices();
|
|
||||||
AstNode::Or { lhs, rhs }
|
|
||||||
}
|
|
||||||
Tag::And => {
|
|
||||||
let (lhs, rhs) = data.as_two_indices();
|
|
||||||
AstNode::And { lhs, rhs }
|
|
||||||
}
|
|
||||||
Tag::BitOr => {
|
|
||||||
let (lhs, rhs) = data.as_two_indices();
|
|
||||||
AstNode::BitOr { lhs, rhs }
|
|
||||||
}
|
|
||||||
Tag::BitXOr => {
|
|
||||||
let (lhs, rhs) = data.as_two_indices();
|
|
||||||
AstNode::BitXOr { lhs, rhs }
|
|
||||||
}
|
|
||||||
Tag::BitAnd => {
|
|
||||||
let (lhs, rhs) = data.as_two_indices();
|
|
||||||
AstNode::BitAnd { lhs, rhs }
|
|
||||||
}
|
|
||||||
Tag::Eq => {
|
|
||||||
let (lhs, rhs) = data.as_two_indices();
|
|
||||||
AstNode::Eq { lhs, rhs }
|
|
||||||
}
|
|
||||||
Tag::NEq => {
|
|
||||||
let (lhs, rhs) = data.as_two_indices();
|
|
||||||
AstNode::NEq { lhs, rhs }
|
|
||||||
}
|
|
||||||
Tag::Lt => {
|
|
||||||
let (lhs, rhs) = data.as_two_indices();
|
|
||||||
AstNode::Lt { lhs, rhs }
|
|
||||||
}
|
|
||||||
Tag::Gt => {
|
|
||||||
let (lhs, rhs) = data.as_two_indices();
|
|
||||||
AstNode::Gt { lhs, rhs }
|
|
||||||
}
|
|
||||||
Tag::Le => {
|
|
||||||
let (lhs, rhs) = data.as_two_indices();
|
|
||||||
AstNode::Le { lhs, rhs }
|
|
||||||
}
|
|
||||||
Tag::Ge => {
|
|
||||||
let (lhs, rhs) = data.as_two_indices();
|
|
||||||
AstNode::Ge { lhs, rhs }
|
|
||||||
}
|
|
||||||
Tag::Shl => {
|
|
||||||
let (lhs, rhs) = data.as_two_indices();
|
|
||||||
AstNode::Shl { lhs, rhs }
|
|
||||||
}
|
|
||||||
Tag::Shr => {
|
|
||||||
let (lhs, rhs) = data.as_two_indices();
|
|
||||||
AstNode::Shr { lhs, rhs }
|
|
||||||
}
|
|
||||||
Tag::Add => {
|
|
||||||
let (lhs, rhs) = data.as_two_indices();
|
|
||||||
AstNode::Add { lhs, rhs }
|
|
||||||
}
|
|
||||||
Tag::Sub => {
|
|
||||||
let (lhs, rhs) = data.as_two_indices();
|
|
||||||
AstNode::Sub { lhs, rhs }
|
|
||||||
}
|
|
||||||
Tag::Mul => {
|
|
||||||
let (lhs, rhs) = data.as_two_indices();
|
|
||||||
AstNode::Mul { lhs, rhs }
|
|
||||||
}
|
|
||||||
Tag::Div => {
|
|
||||||
let (lhs, rhs) = data.as_two_indices();
|
|
||||||
AstNode::Div { lhs, rhs }
|
|
||||||
}
|
|
||||||
Tag::Rem => {
|
|
||||||
let (lhs, rhs) = data.as_two_indices();
|
|
||||||
AstNode::Rem { lhs, rhs }
|
|
||||||
}
|
|
||||||
Tag::Assign => {
|
|
||||||
let (lhs, rhs) = data.as_two_indices();
|
|
||||||
AstNode::Assign { lhs, rhs }
|
|
||||||
}
|
|
||||||
Tag::SubscriptExpr => {
|
|
||||||
let (lhs, index) = data.as_two_indices();
|
|
||||||
AstNode::SubscriptExpr { lhs, index }
|
|
||||||
}
|
|
||||||
Tag::IfExpr => {
|
|
||||||
let (cond, body) = data.as_two_indices();
|
|
||||||
AstNode::IfExpr { cond, body }
|
|
||||||
}
|
|
||||||
Tag::IfElseExpr => {
|
|
||||||
let (cond, extra) = data.as_index_and_extra_offset();
|
|
||||||
let [a, b] = self.extra[extra..][..2] else {
|
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
|
|
||||||
AstNode::IfElseExpr {
|
|
||||||
cond,
|
|
||||||
a: Index::from_u32(a).unwrap(),
|
|
||||||
b: Index::from_u32(b).unwrap(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Tag::Error => AstNode::Error {
|
|
||||||
err: data.as_error(),
|
|
||||||
},
|
|
||||||
Tag::Undefined => AstNode::Undefined,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
||||||
pub enum AstNode {
|
|
||||||
/// pseudo tag, contains a range from a..b into extra of all files.
|
|
||||||
Root {
|
|
||||||
files: Vec<Index>,
|
|
||||||
},
|
|
||||||
/// `data` is a range from a..b into extra of all global nodes.
|
|
||||||
File {
|
|
||||||
decls: Vec<Index>,
|
|
||||||
},
|
|
||||||
/// `data` is an intern to a name, and an index into extra of [index: return_type, index: ParameterList]
|
|
||||||
FunctionProto {
|
|
||||||
name: Interned,
|
|
||||||
return_type: Index,
|
|
||||||
parameter_list: Index,
|
|
||||||
},
|
|
||||||
/// `data` is an intern to a name, and an intern to the function type
|
|
||||||
FunctionProtoInterned {
|
|
||||||
name: Interned,
|
|
||||||
ty: Interned,
|
|
||||||
},
|
|
||||||
/// `data` is an index to a FunctionProto and an index to a Block
|
|
||||||
FunctionDecl {
|
|
||||||
proto: Index,
|
|
||||||
body: Index,
|
|
||||||
},
|
|
||||||
/// `data` is a range from a..b into extra of indices to parameters
|
|
||||||
ParameterList {
|
|
||||||
params: Vec<Index>,
|
|
||||||
},
|
|
||||||
/// `data` is an index to a type, and an intern to a name
|
|
||||||
Parameter {
|
|
||||||
ty: Index,
|
|
||||||
name: Interned,
|
|
||||||
},
|
|
||||||
/// `data` is range from a..b into `extra` of indices to statements
|
|
||||||
Block {
|
|
||||||
statements: Vec<Index>,
|
|
||||||
expr: Option<Index>,
|
|
||||||
},
|
|
||||||
/// `data` is an index to a type, and an intern to a value
|
|
||||||
Constant {
|
|
||||||
ty: Index,
|
|
||||||
value: Interned,
|
|
||||||
},
|
|
||||||
/// `data` is an index to an expression
|
|
||||||
ExprStmt {
|
|
||||||
expr: Index,
|
|
||||||
},
|
|
||||||
/// `data` is none
|
|
||||||
ReturnStmt,
|
|
||||||
/// `data` is an index to an expr
|
|
||||||
ReturnExprStmt {
|
|
||||||
expr: Index,
|
|
||||||
},
|
|
||||||
/// `data` is a range from a..b into `extra` of `[name: intern, type: index]`
|
|
||||||
VarDecl {
|
|
||||||
name: Interned,
|
|
||||||
ty: Index,
|
|
||||||
},
|
|
||||||
/// `data` is a range from a..b into `extra` of `[name: intern, type: index]`
|
|
||||||
MutVarDecl {
|
|
||||||
name: Interned,
|
|
||||||
ty: Index,
|
|
||||||
},
|
|
||||||
/// `data` is a range from a..b into `extra` of `[name: intern, expr: index, type?: index]`
|
|
||||||
VarDeclAssignment {
|
|
||||||
name: Interned,
|
|
||||||
expr: Index,
|
|
||||||
ty: Option<Index>,
|
|
||||||
},
|
|
||||||
/// `data` is a range from a..b into `extra` of `[name: intern, expr: index, type?: index]`
|
|
||||||
MutVarDeclAssignment {
|
|
||||||
name: Interned,
|
|
||||||
expr: Index,
|
|
||||||
ty: Option<Index>,
|
|
||||||
},
|
|
||||||
/// `data` is an intern to a name, and an offset into `extra` of `[type: index, expr: index]`
|
|
||||||
GlobalDecl {
|
|
||||||
name: Interned,
|
|
||||||
expr: Index,
|
|
||||||
ty: Index,
|
|
||||||
},
|
|
||||||
/// `data` is an intern to a name, and an offset into extra of `[flags, type0 ,..., typeN ,name0 ,..., nameN]`
|
|
||||||
StructDecl {
|
|
||||||
name: Interned,
|
|
||||||
flags: StructFlags,
|
|
||||||
field_names: Vec<Interned>,
|
|
||||||
field_types: Vec<Index>,
|
|
||||||
},
|
|
||||||
/// `data` is an intern to a name, and an intern to the type of the struct
|
|
||||||
StructDeclInterned {
|
|
||||||
name: Interned,
|
|
||||||
ty: Interned,
|
|
||||||
},
|
|
||||||
/// `data` is an index to a type, and an intern to a name
|
|
||||||
FieldDecl {
|
|
||||||
name: Interned,
|
|
||||||
ty: Index,
|
|
||||||
},
|
|
||||||
/// `data` is an index to a Parameter, VarDecl, GlobalDecl or FunctionDecl, and an opaque DeclKind
|
|
||||||
DeclRef {
|
|
||||||
decl: Index,
|
|
||||||
},
|
|
||||||
/// `data` is an inlined key into the symbol table (scope: index, name: intern)
|
|
||||||
DeclRefUnresolved {
|
|
||||||
scope: Index,
|
|
||||||
name: Interned,
|
|
||||||
},
|
|
||||||
/// `data` is an intern of a type
|
|
||||||
InternedType {
|
|
||||||
intern: Interned,
|
|
||||||
},
|
|
||||||
/// `data` is an index to a StructDecl
|
|
||||||
TypeDeclRef {
|
|
||||||
decl: Index,
|
|
||||||
},
|
|
||||||
/// `data` is an inlined key into the symbol table (scope: index, name: intern)
|
|
||||||
TypeDeclRefUnresolved {
|
|
||||||
scope: Index,
|
|
||||||
name: Interned,
|
|
||||||
},
|
|
||||||
/// `data` is an index to a Type and u32 PointerFlags (extra offset)
|
|
||||||
PointerType {
|
|
||||||
ty: Index,
|
|
||||||
flags: PointerFlags,
|
|
||||||
},
|
|
||||||
/// `data` is an index to a length expression, and an underlying pointer type
|
|
||||||
ArrayType {
|
|
||||||
length: Index,
|
|
||||||
pointer: Index,
|
|
||||||
},
|
|
||||||
/// `data` is an index to an expr and an index to an ArgumentList
|
|
||||||
CallExpr {
|
|
||||||
func: Index,
|
|
||||||
argument_list: Index,
|
|
||||||
},
|
|
||||||
/// `data` is an index to an expr and an intern to a field name
|
|
||||||
FieldAccess {
|
|
||||||
field_name: Interned,
|
|
||||||
expr: Index,
|
|
||||||
},
|
|
||||||
/// `data` is a range from a..b into extra of indices to arguments
|
|
||||||
ArgumentList {
|
|
||||||
arguments: Vec<Index>,
|
|
||||||
},
|
|
||||||
/// `data` is an index to an expression
|
|
||||||
Argument {
|
|
||||||
expr: Index,
|
|
||||||
name: Option<Interned>,
|
|
||||||
},
|
|
||||||
/// `data` is an index to lhs, and an index to the type
|
|
||||||
ExplicitCast {
|
|
||||||
expr: Index,
|
|
||||||
ty: Index,
|
|
||||||
},
|
|
||||||
/// `data` is a single index to an expr
|
|
||||||
Deref {
|
|
||||||
expr: Index,
|
|
||||||
},
|
|
||||||
AddressOf {
|
|
||||||
expr: Index,
|
|
||||||
},
|
|
||||||
Not {
|
|
||||||
expr: Index,
|
|
||||||
},
|
|
||||||
Negate {
|
|
||||||
expr: Index,
|
|
||||||
},
|
|
||||||
PlaceToValueConversion {
|
|
||||||
expr: Index,
|
|
||||||
},
|
|
||||||
ValueToPlaceConversion {
|
|
||||||
expr: Index,
|
|
||||||
},
|
|
||||||
/// data is two indices for `lhs` and `rhs`
|
|
||||||
Or {
|
|
||||||
lhs: Index,
|
|
||||||
rhs: Index,
|
|
||||||
},
|
|
||||||
And {
|
|
||||||
lhs: Index,
|
|
||||||
rhs: Index,
|
|
||||||
},
|
|
||||||
BitOr {
|
|
||||||
lhs: Index,
|
|
||||||
rhs: Index,
|
|
||||||
},
|
|
||||||
BitXOr {
|
|
||||||
lhs: Index,
|
|
||||||
rhs: Index,
|
|
||||||
},
|
|
||||||
BitAnd {
|
|
||||||
lhs: Index,
|
|
||||||
rhs: Index,
|
|
||||||
},
|
|
||||||
Eq {
|
|
||||||
lhs: Index,
|
|
||||||
rhs: Index,
|
|
||||||
},
|
|
||||||
NEq {
|
|
||||||
lhs: Index,
|
|
||||||
rhs: Index,
|
|
||||||
},
|
|
||||||
Lt {
|
|
||||||
lhs: Index,
|
|
||||||
rhs: Index,
|
|
||||||
},
|
|
||||||
Gt {
|
|
||||||
lhs: Index,
|
|
||||||
rhs: Index,
|
|
||||||
},
|
|
||||||
Le {
|
|
||||||
lhs: Index,
|
|
||||||
rhs: Index,
|
|
||||||
},
|
|
||||||
Ge {
|
|
||||||
lhs: Index,
|
|
||||||
rhs: Index,
|
|
||||||
},
|
|
||||||
Shl {
|
|
||||||
lhs: Index,
|
|
||||||
rhs: Index,
|
|
||||||
},
|
|
||||||
Shr {
|
|
||||||
lhs: Index,
|
|
||||||
rhs: Index,
|
|
||||||
},
|
|
||||||
Add {
|
|
||||||
lhs: Index,
|
|
||||||
rhs: Index,
|
|
||||||
},
|
|
||||||
Sub {
|
|
||||||
lhs: Index,
|
|
||||||
rhs: Index,
|
|
||||||
},
|
|
||||||
Mul {
|
|
||||||
lhs: Index,
|
|
||||||
rhs: Index,
|
|
||||||
},
|
|
||||||
Div {
|
|
||||||
lhs: Index,
|
|
||||||
rhs: Index,
|
|
||||||
},
|
|
||||||
Rem {
|
|
||||||
lhs: Index,
|
|
||||||
rhs: Index,
|
|
||||||
},
|
|
||||||
Assign {
|
|
||||||
lhs: Index,
|
|
||||||
rhs: Index,
|
|
||||||
},
|
|
||||||
SubscriptExpr {
|
|
||||||
lhs: Index,
|
|
||||||
index: Index,
|
|
||||||
},
|
|
||||||
IfExpr {
|
|
||||||
cond: Index,
|
|
||||||
body: Index,
|
|
||||||
},
|
|
||||||
/// `data` is an index to an expression and an index into extra for [if, else]
|
|
||||||
IfElseExpr {
|
|
||||||
cond: Index,
|
|
||||||
a: Index,
|
|
||||||
b: Index,
|
|
||||||
},
|
|
||||||
// TODO:
|
|
||||||
/// `data` is a ParseError
|
|
||||||
Error {
|
|
||||||
err: ParseError,
|
|
||||||
},
|
|
||||||
/// placeholder tag for reserved indices/nodes, `data` is none
|
|
||||||
Undefined,
|
|
||||||
}
|
|
|
@ -1,499 +0,0 @@
|
||||||
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,
|
|
||||||
DerefNonPointer,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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_interned_type_impl(
|
|
||||||
&mut self,
|
|
||||||
ast: &'a mut Ast,
|
|
||||||
idx: Index,
|
|
||||||
intern: intern::Index,
|
|
||||||
) -> Result<Self::Value, Self::Error> {
|
|
||||||
Ok(Some(intern))
|
|
||||||
}
|
|
||||||
|
|
||||||
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_file(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 => self.visit_struct_decl_interned(ast, idx)?,
|
|
||||||
Tag::FunctionDecl => self.visit_function_decl(ast, idx)?,
|
|
||||||
Tag::ParameterList => todo!(),
|
|
||||||
Tag::Block | Tag::BlockTrailingExpr => self.visit_block(ast, idx)?,
|
|
||||||
Tag::Constant => self.visit_constant(ast, idx)?,
|
|
||||||
Tag::ExprStmt => self.visit_expr_stmt(ast, idx)?,
|
|
||||||
Tag::ReturnStmt => self.visit_return_stmt(ast, idx)?,
|
|
||||||
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 => self.visit_explicit_cast(ast, idx)?,
|
|
||||||
Tag::Deref => self.visit_deref(ast, idx)?,
|
|
||||||
Tag::AddressOf => self.visit_address_of(ast, idx)?,
|
|
||||||
Tag::Not | Tag::Negate => {
|
|
||||||
let ty = self.visit_any(ast, data.as_index())?;
|
|
||||||
ty
|
|
||||||
}
|
|
||||||
Tag::PlaceToValueConversion => self.visit_place_to_value_conversion(ast, idx)?,
|
|
||||||
Tag::ValueToPlaceConversion => self.visit_value_to_place_conversion(ast, idx)?,
|
|
||||||
Tag::Or
|
|
||||||
| Tag::And
|
|
||||||
| Tag::BitOr
|
|
||||||
| Tag::BitXOr
|
|
||||||
| Tag::BitAnd
|
|
||||||
| Tag::Eq
|
|
||||||
| Tag::NEq
|
|
||||||
| Tag::Lt
|
|
||||||
| Tag::Gt
|
|
||||||
| Tag::Le
|
|
||||||
| Tag::Ge
|
|
||||||
| Tag::Shl
|
|
||||||
| Tag::Shr
|
|
||||||
| Tag::Add
|
|
||||||
| Tag::Sub
|
|
||||||
| Tag::Mul
|
|
||||||
| Tag::Div
|
|
||||||
| Tag::Rem => {
|
|
||||||
let (lhs, rhs) = data.as_two_indices();
|
|
||||||
let lhs = self.visit_any(ast, lhs)?.unwrap();
|
|
||||||
let rhs = self.visit_any(ast, rhs)?.unwrap();
|
|
||||||
|
|
||||||
if lhs != rhs {
|
|
||||||
self.errors.push(Error {
|
|
||||||
idx,
|
|
||||||
kind: ErrorKind::MismatchingTypes,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(lhs)
|
|
||||||
}
|
|
||||||
Tag::Assign => self.visit_assign(ast, idx)?,
|
|
||||||
Tag::SubscriptExpr => self.visit_subscript_expr(ast, idx)?,
|
|
||||||
Tag::IfExpr => self.visit_if_expr(ast, idx)?,
|
|
||||||
Tag::IfElseExpr => self.visit_if_else_expr(ast, idx)?,
|
|
||||||
Tag::Error => todo!(),
|
|
||||||
Tag::Undefined => todo!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_explicit_cast_impl(
|
|
||||||
&mut self,
|
|
||||||
ast: &'a mut Ast,
|
|
||||||
idx: Index,
|
|
||||||
expr: Index,
|
|
||||||
ty: Index,
|
|
||||||
) -> Result<Self::Value, Self::Error> {
|
|
||||||
_ = self.visit_any(ast, expr)?;
|
|
||||||
// TODO: make sure this cast is legal
|
|
||||||
let ty = self.visit_any(ast, ty)?;
|
|
||||||
|
|
||||||
Ok(ty)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_address_of_impl(
|
|
||||||
&mut self,
|
|
||||||
ast: &'a mut Ast,
|
|
||||||
idx: Index,
|
|
||||||
expr: Index,
|
|
||||||
) -> Result<Self::Value, Self::Error> {
|
|
||||||
self.visit_any(ast, expr)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_deref_impl(
|
|
||||||
&mut self,
|
|
||||||
ast: &'a mut Ast,
|
|
||||||
idx: Index,
|
|
||||||
expr: Index,
|
|
||||||
) -> Result<Self::Value, Self::Error> {
|
|
||||||
let ty = self.visit_any(ast, expr)?.unwrap();
|
|
||||||
if let intern::Key::PointerType { pointee, .. } = self.ip.get_key(ty) {
|
|
||||||
Ok(Some(pointee))
|
|
||||||
} else {
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_place_to_value_conversion_impl(
|
|
||||||
&mut self,
|
|
||||||
ast: &'a mut Ast,
|
|
||||||
idx: Index,
|
|
||||||
expr: Index,
|
|
||||||
) -> Result<Self::Value, Self::Error> {
|
|
||||||
let ty = self.visit_any(ast, expr)?;
|
|
||||||
|
|
||||||
if let Some(ty) = ty {
|
|
||||||
Ok(self.ip.try_get_pointee_type(ty))
|
|
||||||
} else {
|
|
||||||
self.errors.push(Error {
|
|
||||||
idx,
|
|
||||||
kind: ErrorKind::DerefNonPointer,
|
|
||||||
});
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_value_to_place_conversion_impl(
|
|
||||||
&mut self,
|
|
||||||
ast: &'a mut Ast,
|
|
||||||
idx: Index,
|
|
||||||
expr: Index,
|
|
||||||
) -> Result<Self::Value, Self::Error> {
|
|
||||||
let ty = self.visit_any(ast, expr)?;
|
|
||||||
|
|
||||||
if let Some(ty) = ty {
|
|
||||||
Ok(Some(self.ip.get_pointer_type(ty, None)))
|
|
||||||
} else {
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_if_else_expr_impl(
|
|
||||||
&mut self,
|
|
||||||
ast: &'a mut Ast,
|
|
||||||
idx: Index,
|
|
||||||
cond: Index,
|
|
||||||
a: Index,
|
|
||||||
b: Index,
|
|
||||||
) -> Result<Self::Value, Self::Error> {
|
|
||||||
self.visit_any(ast, cond)?;
|
|
||||||
let a = self.visit_block(ast, a)?;
|
|
||||||
let b = self.visit_block(ast, b)?;
|
|
||||||
|
|
||||||
if a != b {
|
|
||||||
self.errors.push(Error {
|
|
||||||
idx,
|
|
||||||
kind: ErrorKind::MismatchingTypes,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(a)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_if_expr_impl(
|
|
||||||
&mut self,
|
|
||||||
ast: &'a mut Ast,
|
|
||||||
idx: Index,
|
|
||||||
cond: Index,
|
|
||||||
body: Index,
|
|
||||||
) -> Result<Self::Value, Self::Error> {
|
|
||||||
self.visit_any(ast, cond)?;
|
|
||||||
self.visit_block(ast, body)?;
|
|
||||||
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_subscript_expr_impl(
|
|
||||||
&mut self,
|
|
||||||
ast: &'a mut Ast,
|
|
||||||
idx: Index,
|
|
||||||
lhs: Index,
|
|
||||||
index: Index,
|
|
||||||
) -> Result<Self::Value, Self::Error> {
|
|
||||||
let lhs = self.visit_any(ast, lhs)?.unwrap();
|
|
||||||
let index = self.visit_any(ast, index)?.unwrap();
|
|
||||||
|
|
||||||
if index != intern::Index::USIZE {
|
|
||||||
self.errors.push(Error {
|
|
||||||
idx,
|
|
||||||
kind: ErrorKind::MismatchingTypes,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let pointee = self.ip.try_get_pointee_type(lhs).unwrap();
|
|
||||||
let pointer = self.ip.get_pointer_type(pointee, None);
|
|
||||||
|
|
||||||
Ok(Some(pointer))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_assign_impl(
|
|
||||||
&mut self,
|
|
||||||
ast: &'a mut Ast,
|
|
||||||
idx: Index,
|
|
||||||
lhs: Index,
|
|
||||||
rhs: Index,
|
|
||||||
) -> Result<Self::Value, Self::Error> {
|
|
||||||
let lhs = self.visit_any(ast, lhs)?.unwrap();
|
|
||||||
let rhs = self.visit_any(ast, rhs)?.unwrap();
|
|
||||||
|
|
||||||
if self.ip.try_get_pointee_type(lhs) != Some(rhs) {
|
|
||||||
self.errors.push(Error {
|
|
||||||
idx,
|
|
||||||
kind: ErrorKind::MismatchingTypes,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +1,7 @@
|
||||||
use crate::{ast2::tag::AstNode, variant};
|
use super::*;
|
||||||
|
|
||||||
use super::{tag::AstNodeExt, *};
|
|
||||||
|
|
||||||
pub trait AstExt {
|
pub trait AstExt {
|
||||||
fn get_node_children(&self, node: Index) -> Vec<Index>;
|
fn get_node_children(&self, node: Index) -> Vec<Index>;
|
||||||
fn get_node_tag_and_data(&self, node: Index) -> (Tag, Data);
|
fn get_node_tag_and_data(&self, node: Index) -> (Tag, Data);
|
||||||
|
|
||||||
fn get_node_data_for_tag(&self, idx: Index, tag: Tag) -> Option<Data> {
|
|
||||||
let (t, data) = self.get_node_tag_and_data(idx);
|
|
||||||
if t == tag {
|
|
||||||
Some(data)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn expect_node_data_for_tag(&self, idx: Index, tag: Tag) -> Data {
|
|
||||||
self.get_node_data_for_tag(idx, tag)
|
|
||||||
.expect(&format!("node {idx} is not a {tag:?}"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AstExt for &Ast {
|
impl AstExt for &Ast {
|
||||||
|
@ -30,7 +13,6 @@ impl AstExt for &Ast {
|
||||||
(self.tags[node], self.datas[node])
|
(self.tags[node], self.datas[node])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AstExt for &mut Ast {
|
impl AstExt for &mut Ast {
|
||||||
fn get_node_children(&self, node: Index) -> Vec<Index> {
|
fn get_node_children(&self, node: Index) -> Vec<Index> {
|
||||||
Ast::get_node_children(self, node)
|
Ast::get_node_children(self, node)
|
||||||
|
@ -254,372 +236,393 @@ impl Ast {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! tag_visit_fn {
|
impl Ast {
|
||||||
($($tag:tt {$($field_name:ident : $field_ty:ty),* $(,)?}),* $(,)?) => {
|
pub fn visit_all_functions_mut<V>(&mut self, visitor: &mut impl AstVisitorTrait) {
|
||||||
$(
|
for i in
|
||||||
paste::paste! {
|
(0..self.tags.functions.len()).map(|i| Index::new(Kind::Function, i as u32).unwrap())
|
||||||
|
{
|
||||||
|
visitor.visit_function_decl(self, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn [<visit_ $tag:snake>](&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
pub fn visit_function_mut<F: FnMut(&mut Self)>(&mut self) {}
|
||||||
variant!(ast.get_ast_node(idx) => AstNode::$tag { $($field_name),* });
|
|
||||||
self.[<visit_ $tag:snake _impl>](ast, idx, $($field_name),*)
|
|
||||||
}
|
|
||||||
fn [<visit_ $tag:snake _impl>](&mut self, ast: Ast, idx: Index, $($field_name: $field_ty),*) -> Result<Self::Value, Self::Error> {
|
|
||||||
_ = (ast, idx, $($field_name),*);
|
|
||||||
Err(Self::UNIMPL)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
use intern::Index as Interned;
|
pub trait AstVisitorTrait {
|
||||||
|
|
||||||
pub trait AstVisitorTrait<Ast: AstExt + AstNodeExt> {
|
|
||||||
type Error;
|
type Error;
|
||||||
type Value;
|
type Value;
|
||||||
const UNIMPL: Self::Error;
|
const UNIMPL: Self::Error;
|
||||||
|
|
||||||
tag_visit_fn!(
|
fn visit_function_decl(
|
||||||
File {
|
&mut self,
|
||||||
decls: Vec<Index>,
|
ast: &mut Ast,
|
||||||
},
|
idx: Index,
|
||||||
FunctionProto {
|
) -> Result<Self::Value, Self::Error> {
|
||||||
name: Interned,
|
_ = (ast, idx);
|
||||||
return_type: Index,
|
Err(Self::UNIMPL)
|
||||||
parameter_list: Index,
|
}
|
||||||
},
|
fn visit_parameter(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
FunctionProtoInterned {
|
_ = (ast, idx);
|
||||||
name: Interned,
|
Err(Self::UNIMPL)
|
||||||
ty: Interned,
|
}
|
||||||
},
|
fn visit_parameter_list(
|
||||||
FunctionDecl {
|
&mut self,
|
||||||
proto: Index,
|
ast: &mut Ast,
|
||||||
body: Index,
|
idx: Index,
|
||||||
},
|
) -> Result<Self::Value, Self::Error> {
|
||||||
ParameterList {
|
_ = (ast, idx);
|
||||||
params: Vec<Index>,
|
Err(Self::UNIMPL)
|
||||||
},
|
}
|
||||||
Parameter {
|
fn visit_block(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
ty: Index,
|
_ = (ast, idx);
|
||||||
name: Interned,
|
Err(Self::UNIMPL)
|
||||||
},
|
}
|
||||||
Block {
|
fn visit_block_trailing_expr(
|
||||||
statements: Vec<Index>,
|
&mut self,
|
||||||
expr: Option<Index>,
|
ast: &mut Ast,
|
||||||
},
|
idx: Index,
|
||||||
Constant {
|
) -> Result<Self::Value, Self::Error> {
|
||||||
ty: Index,
|
_ = (ast, idx);
|
||||||
value: Interned,
|
Err(Self::UNIMPL)
|
||||||
},
|
}
|
||||||
ExprStmt {
|
fn visit_block_maybe_trailing(
|
||||||
expr: Index,
|
&mut self,
|
||||||
},
|
ast: &mut Ast,
|
||||||
ReturnStmt {},
|
idx: Index,
|
||||||
ReturnExprStmt {
|
) -> Result<Self::Value, Self::Error> {
|
||||||
expr: Index,
|
use visitor::AstExt;
|
||||||
},
|
match ast.get_node_tag_and_data(idx).0 {
|
||||||
VarDecl {
|
Tag::BlockTrailingExpr => self.visit_block(ast, idx),
|
||||||
name: Interned,
|
Tag::Block => self.visit_block_trailing_expr(ast, idx),
|
||||||
ty: Index,
|
_ => unreachable!(),
|
||||||
},
|
}
|
||||||
MutVarDecl {
|
}
|
||||||
name: Interned,
|
fn visit_function_proto(
|
||||||
ty: Index,
|
&mut self,
|
||||||
},
|
ast: &mut Ast,
|
||||||
VarDeclAssignment {
|
idx: Index,
|
||||||
name: Interned,
|
) -> Result<Self::Value, Self::Error> {
|
||||||
expr: Index,
|
_ = (ast, idx);
|
||||||
ty: Option<Index>,
|
Err(Self::UNIMPL)
|
||||||
},
|
}
|
||||||
MutVarDeclAssignment {
|
fn visit_call_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
name: Interned,
|
_ = (ast, idx);
|
||||||
expr: Index,
|
Err(Self::UNIMPL)
|
||||||
ty: Option<Index>,
|
}
|
||||||
},
|
fn visit_add_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
GlobalDecl {
|
_ = (ast, idx);
|
||||||
name: Interned,
|
Err(Self::UNIMPL)
|
||||||
expr: Index,
|
}
|
||||||
ty: Index,
|
fn visit_sub_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
},
|
_ = (ast, idx);
|
||||||
StructDecl {
|
Err(Self::UNIMPL)
|
||||||
name: Interned,
|
}
|
||||||
flags: StructFlags,
|
fn visit_mul_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
field_names: Vec<Interned>,
|
_ = (ast, idx);
|
||||||
field_types: Vec<Index>,
|
Err(Self::UNIMPL)
|
||||||
},
|
}
|
||||||
StructDeclInterned {
|
fn visit_div_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
name: Interned,
|
_ = (ast, idx);
|
||||||
ty: Interned,
|
Err(Self::UNIMPL)
|
||||||
},
|
}
|
||||||
FieldDecl {
|
fn visit_rem_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
name: Interned,
|
_ = (ast, idx);
|
||||||
ty: Index,
|
Err(Self::UNIMPL)
|
||||||
},
|
}
|
||||||
DeclRef {
|
fn visit_eq_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
decl: Index,
|
_ = (ast, idx);
|
||||||
},
|
Err(Self::UNIMPL)
|
||||||
DeclRefUnresolved {
|
}
|
||||||
scope: Index,
|
fn visit_neq_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
name: Interned,
|
_ = (ast, idx);
|
||||||
},
|
Err(Self::UNIMPL)
|
||||||
InternedType {
|
}
|
||||||
intern: Interned,
|
fn visit_lt_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
},
|
_ = (ast, idx);
|
||||||
TypeDeclRef {
|
Err(Self::UNIMPL)
|
||||||
decl: Index,
|
}
|
||||||
},
|
fn visit_gt_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
TypeDeclRefUnresolved {
|
_ = (ast, idx);
|
||||||
scope: Index,
|
Err(Self::UNIMPL)
|
||||||
name: Interned,
|
}
|
||||||
},
|
fn visit_le_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
PointerType {
|
_ = (ast, idx);
|
||||||
ty: Index,
|
Err(Self::UNIMPL)
|
||||||
flags: PointerFlags,
|
}
|
||||||
},
|
fn visit_ge_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
ArrayType {
|
_ = (ast, idx);
|
||||||
length: Index,
|
Err(Self::UNIMPL)
|
||||||
pointer: Index,
|
}
|
||||||
},
|
fn visit_shl_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
CallExpr {
|
_ = (ast, idx);
|
||||||
func: Index,
|
Err(Self::UNIMPL)
|
||||||
argument_list: Index,
|
}
|
||||||
},
|
fn visit_shr_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
FieldAccess {
|
_ = (ast, idx);
|
||||||
field_name: Interned,
|
Err(Self::UNIMPL)
|
||||||
expr: Index,
|
}
|
||||||
},
|
fn visit_bitor_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
ArgumentList {
|
_ = (ast, idx);
|
||||||
arguments: Vec<Index>,
|
Err(Self::UNIMPL)
|
||||||
},
|
}
|
||||||
Argument {
|
fn visit_bitxor_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
expr: Index,
|
_ = (ast, idx);
|
||||||
name: Option<Interned>,
|
Err(Self::UNIMPL)
|
||||||
},
|
}
|
||||||
ExplicitCast {
|
fn visit_bitand_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
expr: Index,
|
_ = (ast, idx);
|
||||||
ty: Index,
|
Err(Self::UNIMPL)
|
||||||
},
|
}
|
||||||
Deref {
|
fn visit_or_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
expr: Index,
|
_ = (ast, idx);
|
||||||
},
|
Err(Self::UNIMPL)
|
||||||
AddressOf {
|
}
|
||||||
expr: Index,
|
fn visit_and_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
},
|
_ = (ast, idx);
|
||||||
Not {
|
Err(Self::UNIMPL)
|
||||||
expr: Index,
|
}
|
||||||
},
|
fn visit_not_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
Negate {
|
_ = (ast, idx);
|
||||||
expr: Index,
|
Err(Self::UNIMPL)
|
||||||
},
|
}
|
||||||
PlaceToValueConversion {
|
fn visit_negate_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
expr: Index,
|
_ = (ast, idx);
|
||||||
},
|
Err(Self::UNIMPL)
|
||||||
ValueToPlaceConversion {
|
}
|
||||||
expr: Index,
|
fn visit_deref_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
},
|
_ = (ast, idx);
|
||||||
Or {
|
Err(Self::UNIMPL)
|
||||||
lhs: Index,
|
}
|
||||||
rhs: Index,
|
fn visit_address_of_expr(
|
||||||
},
|
&mut self,
|
||||||
And {
|
ast: &mut Ast,
|
||||||
lhs: Index,
|
idx: Index,
|
||||||
rhs: Index,
|
) -> Result<Self::Value, Self::Error> {
|
||||||
},
|
_ = (ast, idx);
|
||||||
BitOr {
|
Err(Self::UNIMPL)
|
||||||
lhs: Index,
|
}
|
||||||
rhs: Index,
|
fn visit_explicit_cast_expr(
|
||||||
},
|
&mut self,
|
||||||
BitXOr {
|
ast: &mut Ast,
|
||||||
lhs: Index,
|
idx: Index,
|
||||||
rhs: Index,
|
) -> Result<Self::Value, Self::Error> {
|
||||||
},
|
_ = (ast, idx);
|
||||||
BitAnd {
|
Err(Self::UNIMPL)
|
||||||
lhs: Index,
|
}
|
||||||
rhs: Index,
|
fn visit_assign(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
},
|
_ = (ast, idx);
|
||||||
Eq {
|
Err(Self::UNIMPL)
|
||||||
lhs: Index,
|
}
|
||||||
rhs: Index,
|
fn visit_subscript_expr(
|
||||||
},
|
&mut self,
|
||||||
NEq {
|
ast: &mut Ast,
|
||||||
lhs: Index,
|
idx: Index,
|
||||||
rhs: Index,
|
) -> Result<Self::Value, Self::Error> {
|
||||||
},
|
_ = (ast, idx);
|
||||||
Lt {
|
Err(Self::UNIMPL)
|
||||||
lhs: Index,
|
}
|
||||||
rhs: Index,
|
fn visit_if_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
},
|
_ = (ast, idx);
|
||||||
Gt {
|
Err(Self::UNIMPL)
|
||||||
lhs: Index,
|
}
|
||||||
rhs: Index,
|
fn visit_if_else_expr(
|
||||||
},
|
&mut self,
|
||||||
Le {
|
ast: &mut Ast,
|
||||||
lhs: Index,
|
idx: Index,
|
||||||
rhs: Index,
|
) -> Result<Self::Value, Self::Error> {
|
||||||
},
|
_ = (ast, idx);
|
||||||
Ge {
|
Err(Self::UNIMPL)
|
||||||
lhs: Index,
|
}
|
||||||
rhs: Index,
|
fn visit_argument(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
},
|
_ = (ast, idx);
|
||||||
Shl {
|
Err(Self::UNIMPL)
|
||||||
lhs: Index,
|
}
|
||||||
rhs: Index,
|
|
||||||
},
|
|
||||||
Shr {
|
|
||||||
lhs: Index,
|
|
||||||
rhs: Index,
|
|
||||||
},
|
|
||||||
Add {
|
|
||||||
lhs: Index,
|
|
||||||
rhs: Index,
|
|
||||||
},
|
|
||||||
Sub {
|
|
||||||
lhs: Index,
|
|
||||||
rhs: Index,
|
|
||||||
},
|
|
||||||
Mul {
|
|
||||||
lhs: Index,
|
|
||||||
rhs: Index,
|
|
||||||
},
|
|
||||||
Div {
|
|
||||||
lhs: Index,
|
|
||||||
rhs: Index,
|
|
||||||
},
|
|
||||||
Rem {
|
|
||||||
lhs: Index,
|
|
||||||
rhs: Index,
|
|
||||||
},
|
|
||||||
Assign {
|
|
||||||
lhs: Index,
|
|
||||||
rhs: Index,
|
|
||||||
},
|
|
||||||
SubscriptExpr {
|
|
||||||
lhs: Index,
|
|
||||||
index: Index,
|
|
||||||
},
|
|
||||||
IfExpr {
|
|
||||||
cond: Index,
|
|
||||||
body: Index,
|
|
||||||
},
|
|
||||||
IfElseExpr {
|
|
||||||
cond: Index,
|
|
||||||
a: Index,
|
|
||||||
b: Index,
|
|
||||||
},
|
|
||||||
Error {
|
|
||||||
err: ParseError,
|
|
||||||
},
|
|
||||||
Undefined {},
|
|
||||||
);
|
|
||||||
|
|
||||||
fn visit_any(&mut self, ast: Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
fn visit_any_argument(
|
||||||
match ast.get_ast_node(idx) {
|
&mut self,
|
||||||
AstNode::File { decls } => self.visit_file_impl(ast, idx, decls),
|
ast: &mut Ast,
|
||||||
AstNode::FunctionProto {
|
idx: Index,
|
||||||
name,
|
) -> Result<Self::Value, Self::Error> {
|
||||||
return_type,
|
use visitor::AstExt;
|
||||||
parameter_list,
|
match ast.get_node_tag_and_data(idx).0 {
|
||||||
} => self.visit_function_proto_impl(ast, idx, name, return_type, parameter_list),
|
Tag::Argument => self.visit_argument(ast, idx),
|
||||||
AstNode::FunctionProtoInterned { name, ty } => {
|
Tag::NamedArgument => self.visit_named_argument(ast, idx),
|
||||||
self.visit_function_proto_interned_impl(ast, idx, name, ty)
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
AstNode::FunctionDecl { proto, body } => {
|
}
|
||||||
self.visit_function_decl_impl(ast, idx, proto, body)
|
|
||||||
}
|
fn visit_named_argument(
|
||||||
AstNode::ParameterList { params } => self.visit_parameter_list_impl(ast, idx, params),
|
&mut self,
|
||||||
AstNode::Parameter { ty, name } => self.visit_parameter_impl(ast, idx, ty, name),
|
ast: &mut Ast,
|
||||||
AstNode::Block { statements, expr } => {
|
idx: Index,
|
||||||
self.visit_block_impl(ast, idx, statements, expr)
|
) -> Result<Self::Value, Self::Error> {
|
||||||
}
|
_ = (ast, idx);
|
||||||
AstNode::Constant { ty, value } => self.visit_constant_impl(ast, idx, ty, value),
|
Err(Self::UNIMPL)
|
||||||
AstNode::ExprStmt { expr } => self.visit_expr_stmt_impl(ast, idx, expr),
|
}
|
||||||
AstNode::ReturnStmt => self.visit_return_stmt_impl(ast, idx),
|
|
||||||
AstNode::ReturnExprStmt { expr } => self.visit_return_expr_stmt_impl(ast, idx, expr),
|
fn visit_argument_list(
|
||||||
AstNode::VarDecl { name, ty } => self.visit_var_decl_impl(ast, idx, name, ty),
|
&mut self,
|
||||||
AstNode::MutVarDecl { name, ty } => self.visit_mut_var_decl_impl(ast, idx, name, ty),
|
ast: &mut Ast,
|
||||||
AstNode::VarDeclAssignment { name, expr, ty } => {
|
idx: Index,
|
||||||
self.visit_var_decl_assignment_impl(ast, idx, name, expr, ty)
|
) -> Result<Self::Value, Self::Error> {
|
||||||
}
|
_ = (ast, idx);
|
||||||
AstNode::MutVarDeclAssignment { name, expr, ty } => {
|
Err(Self::UNIMPL)
|
||||||
self.visit_mut_var_decl_assignment_impl(ast, idx, name, expr, ty)
|
}
|
||||||
}
|
|
||||||
AstNode::GlobalDecl { name, expr, ty } => {
|
fn visit_constant(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
self.visit_global_decl_impl(ast, idx, name, expr, ty)
|
_ = (ast, idx);
|
||||||
}
|
Err(Self::UNIMPL)
|
||||||
AstNode::StructDecl {
|
}
|
||||||
name,
|
|
||||||
flags,
|
fn visit_return(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
field_names,
|
_ = (ast, idx);
|
||||||
field_types,
|
Err(Self::UNIMPL)
|
||||||
} => self.visit_struct_decl_impl(ast, idx, name, flags, field_names, field_types),
|
}
|
||||||
AstNode::StructDeclInterned { name, ty } => {
|
fn visit_return_expr(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
self.visit_struct_decl_interned_impl(ast, idx, name, ty)
|
_ = (ast, idx);
|
||||||
}
|
Err(Self::UNIMPL)
|
||||||
AstNode::FieldDecl { name, ty } => self.visit_field_decl_impl(ast, idx, name, ty),
|
}
|
||||||
AstNode::DeclRef { decl } => self.visit_decl_ref_impl(ast, idx, decl),
|
fn visit_global_decl(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
AstNode::DeclRefUnresolved { scope, name } => {
|
_ = (ast, idx);
|
||||||
self.visit_decl_ref_unresolved_impl(ast, idx, scope, name)
|
Err(Self::UNIMPL)
|
||||||
}
|
}
|
||||||
AstNode::InternedType { intern } => self.visit_interned_type_impl(ast, idx, intern),
|
fn visit_var_decl(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
AstNode::TypeDeclRef { decl } => self.visit_type_decl_ref_impl(ast, idx, decl),
|
_ = (ast, idx);
|
||||||
AstNode::TypeDeclRefUnresolved { scope, name } => {
|
Err(Self::UNIMPL)
|
||||||
self.visit_type_decl_ref_unresolved_impl(ast, idx, scope, name)
|
}
|
||||||
}
|
fn visit_mut_var_decl(
|
||||||
AstNode::PointerType { ty, flags } => self.visit_pointer_type_impl(ast, idx, ty, flags),
|
&mut self,
|
||||||
AstNode::ArrayType { length, pointer } => {
|
ast: &mut Ast,
|
||||||
self.visit_array_type_impl(ast, idx, length, pointer)
|
idx: Index,
|
||||||
}
|
) -> Result<Self::Value, Self::Error> {
|
||||||
AstNode::CallExpr {
|
_ = (ast, idx);
|
||||||
func,
|
Err(Self::UNIMPL)
|
||||||
argument_list,
|
}
|
||||||
} => self.visit_call_expr_impl(ast, idx, func, argument_list),
|
fn visit_var_assign_decl(
|
||||||
AstNode::FieldAccess { field_name, expr } => {
|
&mut self,
|
||||||
self.visit_field_access_impl(ast, idx, field_name, expr)
|
ast: &mut Ast,
|
||||||
}
|
idx: Index,
|
||||||
AstNode::ArgumentList { arguments } => {
|
) -> Result<Self::Value, Self::Error> {
|
||||||
self.visit_argument_list_impl(ast, idx, arguments)
|
_ = (ast, idx);
|
||||||
}
|
Err(Self::UNIMPL)
|
||||||
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),
|
fn visit_mut_var_assign_decl(
|
||||||
AstNode::Deref { expr } => self.visit_deref_impl(ast, idx, expr),
|
&mut self,
|
||||||
AstNode::AddressOf { expr } => self.visit_address_of_impl(ast, idx, expr),
|
ast: &mut Ast,
|
||||||
AstNode::Not { expr } => self.visit_not_impl(ast, idx, expr),
|
idx: Index,
|
||||||
AstNode::Negate { expr } => self.visit_negate_impl(ast, idx, expr),
|
) -> Result<Self::Value, Self::Error> {
|
||||||
AstNode::PlaceToValueConversion { expr } => {
|
_ = (ast, idx);
|
||||||
self.visit_place_to_value_conversion_impl(ast, idx, expr)
|
Err(Self::UNIMPL)
|
||||||
}
|
}
|
||||||
AstNode::ValueToPlaceConversion { expr } => {
|
fn visit_decl_ref(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
self.visit_value_to_place_conversion_impl(ast, idx, expr)
|
_ = (ast, idx);
|
||||||
}
|
Err(Self::UNIMPL)
|
||||||
AstNode::Or { lhs, rhs } => self.visit_or_impl(ast, idx, lhs, rhs),
|
}
|
||||||
AstNode::And { lhs, rhs } => self.visit_and_impl(ast, idx, lhs, rhs),
|
fn visit_value_to_place_conversion(
|
||||||
AstNode::BitOr { lhs, rhs } => self.visit_bit_or_impl(ast, idx, lhs, rhs),
|
&mut self,
|
||||||
AstNode::BitXOr { lhs, rhs } => self.visit_bit_x_or_impl(ast, idx, lhs, rhs),
|
ast: &mut Ast,
|
||||||
AstNode::BitAnd { lhs, rhs } => self.visit_bit_and_impl(ast, idx, lhs, rhs),
|
idx: Index,
|
||||||
AstNode::Eq { lhs, rhs } => self.visit_eq_impl(ast, idx, lhs, rhs),
|
) -> Result<Self::Value, Self::Error> {
|
||||||
AstNode::NEq { lhs, rhs } => self.visit_n_eq_impl(ast, idx, lhs, rhs),
|
let idx = ast
|
||||||
AstNode::Lt { lhs, rhs } => self.visit_lt_impl(ast, idx, lhs, rhs),
|
.get_node_data_for_tag(idx, Tag::ValueToPlaceConversion)
|
||||||
AstNode::Gt { lhs, rhs } => self.visit_gt_impl(ast, idx, lhs, rhs),
|
.unwrap()
|
||||||
AstNode::Le { lhs, rhs } => self.visit_le_impl(ast, idx, lhs, rhs),
|
.as_index();
|
||||||
AstNode::Ge { lhs, rhs } => self.visit_ge_impl(ast, idx, lhs, rhs),
|
self.visit_any(ast, idx)
|
||||||
AstNode::Shl { lhs, rhs } => self.visit_shl_impl(ast, idx, lhs, rhs),
|
}
|
||||||
AstNode::Shr { lhs, rhs } => self.visit_shr_impl(ast, idx, lhs, rhs),
|
fn visit_place_to_value_conversion(
|
||||||
AstNode::Add { lhs, rhs } => self.visit_add_impl(ast, idx, lhs, rhs),
|
&mut self,
|
||||||
AstNode::Sub { lhs, rhs } => self.visit_sub_impl(ast, idx, lhs, rhs),
|
ast: &mut Ast,
|
||||||
AstNode::Mul { lhs, rhs } => self.visit_mul_impl(ast, idx, lhs, rhs),
|
idx: Index,
|
||||||
AstNode::Div { lhs, rhs } => self.visit_div_impl(ast, idx, lhs, rhs),
|
) -> Result<Self::Value, Self::Error> {
|
||||||
AstNode::Rem { lhs, rhs } => self.visit_rem_impl(ast, idx, lhs, rhs),
|
let idx = ast
|
||||||
AstNode::Assign { lhs, rhs } => self.visit_assign_impl(ast, idx, lhs, rhs),
|
.get_node_data_for_tag(idx, Tag::PlaceToValueConversion)
|
||||||
AstNode::SubscriptExpr { lhs, index: rhs } => {
|
.unwrap()
|
||||||
self.visit_subscript_expr_impl(ast, idx, lhs, rhs)
|
.as_index();
|
||||||
}
|
self.visit_any(ast, idx)
|
||||||
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)
|
fn visit_any(&mut self, ast: &mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
|
||||||
}
|
use visitor::AstExt;
|
||||||
AstNode::Error { err } => self.visit_error_impl(ast, idx, err),
|
match ast.get_node_tag_and_data(idx).0 {
|
||||||
AstNode::Undefined => self.visit_undefined_impl(ast, idx),
|
Tag::FunctionProto => self.visit_function_proto(ast, idx),
|
||||||
AstNode::Root { .. } => unreachable!(),
|
Tag::FunctionDecl => self.visit_function_decl(ast, idx),
|
||||||
|
Tag::ParameterList => self.visit_parameter_list(ast, idx),
|
||||||
|
Tag::Parameter => self.visit_parameter(ast, idx),
|
||||||
|
Tag::Block => self.visit_block(ast, idx),
|
||||||
|
Tag::BlockTrailingExpr => self.visit_block_trailing_expr(ast, idx),
|
||||||
|
Tag::Constant => self.visit_constant(ast, idx),
|
||||||
|
Tag::ExprStmt => todo!(),
|
||||||
|
Tag::ReturnStmt => self.visit_return(ast, idx),
|
||||||
|
Tag::ReturnExprStmt => self.visit_return_expr(ast, idx),
|
||||||
|
Tag::VarDecl => self.visit_var_decl(ast, idx),
|
||||||
|
Tag::MutVarDecl => self.visit_mut_var_decl(ast, idx),
|
||||||
|
Tag::VarDeclAssignment => self.visit_var_assign_decl(ast, idx),
|
||||||
|
Tag::MutVarDeclAssignment => self.visit_mut_var_assign_decl(ast, idx),
|
||||||
|
Tag::GlobalDecl => self.visit_global_decl(ast, idx),
|
||||||
|
Tag::StructDecl => todo!(),
|
||||||
|
Tag::FieldDecl => todo!(),
|
||||||
|
Tag::DeclRef => self.visit_decl_ref(ast, idx),
|
||||||
|
Tag::DeclRefUnresolved => todo!(),
|
||||||
|
Tag::InternedType => todo!(),
|
||||||
|
Tag::TypeDeclRef => todo!(),
|
||||||
|
Tag::TypeDeclRefUnresolved => todo!(),
|
||||||
|
Tag::PointerType => todo!(),
|
||||||
|
Tag::ArrayType => todo!(),
|
||||||
|
Tag::CallExpr => self.visit_call_expr(ast, idx),
|
||||||
|
Tag::FieldAccess => todo!(),
|
||||||
|
Tag::ArgumentList => self.visit_argument_list(ast, idx),
|
||||||
|
Tag::Argument => self.visit_argument(ast, idx),
|
||||||
|
Tag::NamedArgument => self.visit_named_argument(ast, idx),
|
||||||
|
Tag::ExplicitCast => self.visit_explicit_cast_expr(ast, idx),
|
||||||
|
Tag::Deref => self.visit_deref_expr(ast, idx),
|
||||||
|
Tag::AddressOf => self.visit_add_expr(ast, idx),
|
||||||
|
Tag::Not => self.visit_not_expr(ast, idx),
|
||||||
|
Tag::Negate => self.visit_negate_expr(ast, idx),
|
||||||
|
Tag::Or => self.visit_or_expr(ast, idx),
|
||||||
|
Tag::And => self.visit_and_expr(ast, idx),
|
||||||
|
Tag::BitOr => self.visit_bitor_expr(ast, idx),
|
||||||
|
Tag::BitXOr => self.visit_bitxor_expr(ast, idx),
|
||||||
|
Tag::BitAnd => self.visit_bitand_expr(ast, idx),
|
||||||
|
Tag::Eq => self.visit_eq_expr(ast, idx),
|
||||||
|
Tag::NEq => self.visit_neq_expr(ast, idx),
|
||||||
|
Tag::Lt => self.visit_lt_expr(ast, idx),
|
||||||
|
Tag::Gt => self.visit_gt_expr(ast, idx),
|
||||||
|
Tag::Le => self.visit_le_expr(ast, idx),
|
||||||
|
Tag::Ge => self.visit_ge_expr(ast, idx),
|
||||||
|
Tag::Shl => self.visit_shl_expr(ast, idx),
|
||||||
|
Tag::Shr => self.visit_shr_expr(ast, idx),
|
||||||
|
Tag::Add => self.visit_add_expr(ast, idx),
|
||||||
|
Tag::Sub => self.visit_sub_expr(ast, idx),
|
||||||
|
Tag::Mul => self.visit_mul_expr(ast, idx),
|
||||||
|
Tag::Div => self.visit_div_expr(ast, idx),
|
||||||
|
Tag::Rem => self.visit_rem_expr(ast, idx),
|
||||||
|
Tag::Assign => self.visit_assign(ast, idx),
|
||||||
|
Tag::SubscriptExpr => self.visit_subscript_expr(ast, idx),
|
||||||
|
Tag::IfExpr => self.visit_if_expr(ast, idx),
|
||||||
|
Tag::IfElseExpr => self.visit_if_else_expr(ast, idx),
|
||||||
|
Tag::PlaceToValueConversion => self.visit_place_to_value_conversion(ast, idx),
|
||||||
|
Tag::ValueToPlaceConversion => self.visit_value_to_place_conversion(ast, idx),
|
||||||
|
Tag::Error => todo!(),
|
||||||
|
Tag::Undefined => todo!(),
|
||||||
|
Tag::Root => todo!(),
|
||||||
|
Tag::File => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Ast {
|
||||||
|
pub fn get_node_data_for_tag(&self, idx: Index, tag: Tag) -> Option<Data> {
|
||||||
|
use visitor::AstExt;
|
||||||
|
let (t, data) = self.get_node_tag_and_data(idx);
|
||||||
|
if t == tag {
|
||||||
|
Some(data)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn expect_node_data_for_tag(&self, idx: Index, tag: Tag) -> Data {
|
||||||
|
self.get_node_data_for_tag(idx, tag)
|
||||||
|
.expect(&format!("node {idx} is not a {tag:?}"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#![feature(
|
#![feature(
|
||||||
|
extract_if,
|
||||||
iter_advance_by,
|
iter_advance_by,
|
||||||
box_into_inner,
|
box_into_inner,
|
||||||
|
hash_extract_if,
|
||||||
bigint_helper_methods,
|
bigint_helper_methods,
|
||||||
map_try_insert,
|
map_try_insert,
|
||||||
iter_intersperse,
|
iter_intersperse,
|
||||||
|
@ -27,9 +29,6 @@ pub mod symbol_table;
|
||||||
pub mod tokens;
|
pub mod tokens;
|
||||||
pub mod triples;
|
pub mod triples;
|
||||||
|
|
||||||
pub mod utils;
|
|
||||||
use utils::unit;
|
|
||||||
|
|
||||||
pub fn tokenize<'a>(
|
pub fn tokenize<'a>(
|
||||||
bytes: &'a [u8],
|
bytes: &'a [u8],
|
||||||
) -> Result<lexer::Tokenizer<'a>, (lexer::Tokenizer<'a>, Vec<lexer::TokenizeError>)> {
|
) -> Result<lexer::Tokenizer<'a>, (lexer::Tokenizer<'a>, Vec<lexer::TokenizeError>)> {
|
||||||
|
@ -71,3 +70,5 @@ impl BitSize for &[u8] {
|
||||||
bits as u32
|
bits as u32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn unit<T>(_: T) {}
|
||||||
|
|
25
src/utils.rs
25
src/utils.rs
|
@ -1,25 +0,0 @@
|
||||||
use core::{cell::UnsafeCell, mem::ManuallyDrop};
|
|
||||||
|
|
||||||
pub fn unit<T>(_: T) {}
|
|
||||||
|
|
||||||
pub struct DropGuard<F: FnOnce()>(UnsafeCell<ManuallyDrop<F>>);
|
|
||||||
|
|
||||||
impl<F> DropGuard<F>
|
|
||||||
where
|
|
||||||
F: FnOnce(),
|
|
||||||
{
|
|
||||||
pub fn new(f: F) -> DropGuard<F> {
|
|
||||||
Self(UnsafeCell::new(ManuallyDrop::new(f)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<F> Drop for DropGuard<F>
|
|
||||||
where
|
|
||||||
F: FnOnce(),
|
|
||||||
{
|
|
||||||
fn drop(&mut self) {
|
|
||||||
unsafe {
|
|
||||||
ManuallyDrop::take(&mut *self.0.get())();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue