Started AST
This commit is contained in:
parent
3f99fefe87
commit
1ab6bb1e2b
11
src/main.rs
11
src/main.rs
|
@ -10,7 +10,6 @@ use std::ops::Add;
|
||||||
use err::*;
|
use err::*;
|
||||||
use lookahead::*;
|
use lookahead::*;
|
||||||
use parse::*;
|
use parse::*;
|
||||||
use semantic::Analyzer;
|
|
||||||
use token::*;
|
use token::*;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
@ -70,17 +69,7 @@ fn parse(input: &'static str) -> impl Iterator<Item = Statement> {
|
||||||
Parser::new(tokenize(input))
|
Parser::new(tokenize(input))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn typecheck(input: &'static str) {
|
|
||||||
let parsed: Vec<_> = parse(input).collect();
|
|
||||||
let mut s = semantic::Analyzer::new();
|
|
||||||
s.block(parsed);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
for p in parse(include_str!("../demo.hal")) {
|
|
||||||
println!("------------------");
|
|
||||||
println!("{p:#?}");
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
for s in typecheck(include_str!("../demo.hal")) {
|
for s in typecheck(include_str!("../demo.hal")) {
|
||||||
println!("------------------");
|
println!("------------------");
|
||||||
|
|
|
@ -7,7 +7,6 @@ pub struct Parameters {
|
||||||
pub arity: usize,
|
pub arity: usize,
|
||||||
pub names: Vec<String>,
|
pub names: Vec<String>,
|
||||||
pub type_names: Vec<String>,
|
pub type_names: Vec<String>,
|
||||||
pub types: Vec<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Parameters {
|
impl Default for Parameters {
|
||||||
|
@ -16,7 +15,6 @@ impl Default for Parameters {
|
||||||
arity: 0,
|
arity: 0,
|
||||||
names: vec![],
|
names: vec![],
|
||||||
type_names: vec![],
|
type_names: vec![],
|
||||||
types: vec![],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -94,12 +92,16 @@ pub enum ExpressionKind {
|
||||||
pub struct Expression {
|
pub struct Expression {
|
||||||
pub kind: ExpressionKind,
|
pub kind: ExpressionKind,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub type_: Type,
|
pub type_: UID,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Expression {
|
impl Expression {
|
||||||
pub fn new(kind: ExpressionKind, span: Span, type_: Type) -> Self {
|
pub fn new(kind: ExpressionKind, span: Span) -> Self {
|
||||||
Self { kind, span, type_ }
|
Self {
|
||||||
|
kind,
|
||||||
|
span,
|
||||||
|
type_: "".into(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,7 +196,6 @@ impl<I: Iterator<Item = Token>> Parser<I> {
|
||||||
child: child.into(),
|
child: child.into(),
|
||||||
},
|
},
|
||||||
span,
|
span,
|
||||||
Type::Ambiguous,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// Primary
|
// Primary
|
||||||
|
@ -226,7 +227,6 @@ impl<I: Iterator<Item = Token>> Parser<I> {
|
||||||
right: rhs.into(),
|
right: rhs.into(),
|
||||||
},
|
},
|
||||||
span,
|
span,
|
||||||
Type::Ambiguous,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// Field
|
// Field
|
||||||
|
@ -245,7 +245,6 @@ impl<I: Iterator<Item = Token>> Parser<I> {
|
||||||
uid: "".into(),
|
uid: "".into(),
|
||||||
},
|
},
|
||||||
span,
|
span,
|
||||||
Type::Ambiguous,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// Function call
|
// Function call
|
||||||
|
@ -275,7 +274,6 @@ impl<I: Iterator<Item = Token>> Parser<I> {
|
||||||
uid: "".into(),
|
uid: "".into(),
|
||||||
},
|
},
|
||||||
span + span2,
|
span + span2,
|
||||||
Type::Ambiguous,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// Unary postfix
|
// Unary postfix
|
||||||
|
@ -296,7 +294,6 @@ impl<I: Iterator<Item = Token>> Parser<I> {
|
||||||
child: current.into(),
|
child: current.into(),
|
||||||
},
|
},
|
||||||
span,
|
span,
|
||||||
Type::Ambiguous,
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
|
@ -310,7 +307,6 @@ impl<I: Iterator<Item = Token>> Parser<I> {
|
||||||
let mut arity = 0;
|
let mut arity = 0;
|
||||||
let mut names = vec![];
|
let mut names = vec![];
|
||||||
let mut type_names = vec![];
|
let mut type_names = vec![];
|
||||||
let mut types = vec![];
|
|
||||||
let mut strongly_typed = false;
|
let mut strongly_typed = false;
|
||||||
loop {
|
loop {
|
||||||
// Param name
|
// Param name
|
||||||
|
@ -333,7 +329,6 @@ impl<I: Iterator<Item = Token>> Parser<I> {
|
||||||
} else {
|
} else {
|
||||||
type_names.push("".into());
|
type_names.push("".into());
|
||||||
}
|
}
|
||||||
types.push("".into());
|
|
||||||
arity += 1;
|
arity += 1;
|
||||||
// Comma
|
// Comma
|
||||||
if !self.eat(t::Comma).is_ok() {
|
if !self.eat(t::Comma).is_ok() {
|
||||||
|
@ -368,7 +363,6 @@ impl<I: Iterator<Item = Token>> Parser<I> {
|
||||||
arity,
|
arity,
|
||||||
names,
|
names,
|
||||||
type_names,
|
type_names,
|
||||||
types,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -507,7 +501,7 @@ impl<I: Iterator<Item = Token>> Parser<I> {
|
||||||
.reason(format!("Expected expression, found {}", next.0));
|
.reason(format!("Expected expression, found {}", next.0));
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
Ok(Expression::new(kind, span, Type::Ambiguous))
|
Ok(Expression::new(kind, span))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn if_else(&mut self) -> Result<Expression> {
|
fn if_else(&mut self) -> Result<Expression> {
|
||||||
|
@ -526,22 +520,17 @@ impl<I: Iterator<Item = Token>> Parser<I> {
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
Ok(Expression {
|
Ok(Expression::new(
|
||||||
kind: ExpressionKind::If {
|
ExpressionKind::If {
|
||||||
predicate: predicate.into(),
|
predicate: predicate.into(),
|
||||||
block,
|
block,
|
||||||
else_,
|
else_,
|
||||||
},
|
},
|
||||||
span,
|
span,
|
||||||
type_: Type::Ambiguous,
|
))
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
let (block, span) = self.block()?;
|
let (block, span) = self.block()?;
|
||||||
Ok(Expression {
|
Ok(Expression::new(ExpressionKind::Block(block), span))
|
||||||
kind: ExpressionKind::Block(block),
|
|
||||||
span,
|
|
||||||
type_: Type::Ambiguous,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,15 +7,12 @@ pub enum StatementKind {
|
||||||
Declaration {
|
Declaration {
|
||||||
name: String,
|
name: String,
|
||||||
type_str: Option<String>,
|
type_str: Option<String>,
|
||||||
type_uid: UID,
|
|
||||||
value: Expression,
|
value: Expression,
|
||||||
mutable: bool,
|
mutable: bool,
|
||||||
uid: UID,
|
|
||||||
},
|
},
|
||||||
Assignment {
|
Assignment {
|
||||||
name: String,
|
name: String,
|
||||||
value: Expression,
|
value: Expression,
|
||||||
uid: UID,
|
|
||||||
},
|
},
|
||||||
While {
|
While {
|
||||||
predicate: Expression,
|
predicate: Expression,
|
||||||
|
@ -78,10 +75,8 @@ impl<I: Iterator<Item = Token>> Parser<I> {
|
||||||
kind: s::Declaration {
|
kind: s::Declaration {
|
||||||
name,
|
name,
|
||||||
type_str,
|
type_str,
|
||||||
type_uid: "".into(),
|
|
||||||
value,
|
value,
|
||||||
mutable,
|
mutable,
|
||||||
uid: "".into(),
|
|
||||||
},
|
},
|
||||||
span,
|
span,
|
||||||
};
|
};
|
||||||
|
@ -99,11 +94,7 @@ impl<I: Iterator<Item = Token>> Parser<I> {
|
||||||
.trace_span(span, "while parsing assignment")?;
|
.trace_span(span, "while parsing assignment")?;
|
||||||
Statement {
|
Statement {
|
||||||
span,
|
span,
|
||||||
kind: s::Assignment {
|
kind: s::Assignment { name, value },
|
||||||
name,
|
|
||||||
value,
|
|
||||||
uid: "".into(),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// While
|
// While
|
||||||
|
|
|
@ -1,91 +1,3 @@
|
||||||
use crate::{Expression, ExpressionKind, Statement, StatementKind};
|
use crate::{Expression, ExpressionKind, Statement, StatementKind};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub struct Analyzer {
|
|
||||||
table: SymbolTable,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Analyzer {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
table: SymbolTable::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn typecheck() {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Analyzing a block:
|
|
||||||
/// 1. Name structs
|
|
||||||
/// 2. Type structs
|
|
||||||
/// 3. Name and type functions
|
|
||||||
/// 4. Name variables (recurse on blocks) (track moves)
|
|
||||||
/// 5. Type variables
|
|
||||||
/// 6. Type assert variables
|
|
||||||
pub fn block(&mut self, mut block: Vec<Statement>) -> Result<Vec<Statement>> {
|
|
||||||
// 1. Name structs
|
|
||||||
for s in &mut block {
|
|
||||||
if let StatementKind::Declaration {
|
|
||||||
name,
|
|
||||||
value:
|
|
||||||
Expression {
|
|
||||||
kind: ExpressionKind::StructDef(params, _),
|
|
||||||
type_,
|
|
||||||
..
|
|
||||||
},
|
|
||||||
..
|
|
||||||
} = &mut s.kind
|
|
||||||
{
|
|
||||||
*type_ = Type::Nothing;
|
|
||||||
self.table.declare_struct(name, s.span)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 2. Type structs
|
|
||||||
for s in &mut block {
|
|
||||||
if let StatementKind::Declaration {
|
|
||||||
name,
|
|
||||||
value:
|
|
||||||
Expression {
|
|
||||||
kind: ExpressionKind::StructDef(params, _),
|
|
||||||
..
|
|
||||||
},
|
|
||||||
..
|
|
||||||
} = &mut s.kind
|
|
||||||
{
|
|
||||||
self.table.declare_struct(name, s.span)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 3. Name and type functions
|
|
||||||
for s in &mut block {
|
|
||||||
if let StatementKind::Declaration {
|
|
||||||
name,
|
|
||||||
value:
|
|
||||||
Expression {
|
|
||||||
kind:
|
|
||||||
ExpressionKind::FunctionDef {
|
|
||||||
params,
|
|
||||||
returns_str,
|
|
||||||
returns_actual,
|
|
||||||
body,
|
|
||||||
uid,
|
|
||||||
},
|
|
||||||
type_,
|
|
||||||
span,
|
|
||||||
},
|
|
||||||
..
|
|
||||||
} = &mut s.kind
|
|
||||||
{
|
|
||||||
let uid = self.table.define_function(
|
|
||||||
name,
|
|
||||||
params.clone(),
|
|
||||||
returns_str.as_ref().map(|s| s.as_str()),
|
|
||||||
*span,
|
|
||||||
)?;
|
|
||||||
*type_ = Type::Function(uid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(block)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
24
src/semantic/builtin.rs
Normal file
24
src/semantic/builtin.rs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
use super::{UID, primitives::Primitive};
|
||||||
|
|
||||||
|
pub fn mangle(input: &str) -> UID {
|
||||||
|
format!("$${input}")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nothing ever happens
|
||||||
|
pub fn nothing() -> UID {
|
||||||
|
mangle("nothing")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn integer() -> UID {
|
||||||
|
Primitive::integer_ambiguous.mangle()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn real() -> UID {
|
||||||
|
Primitive::real_ambiguous.mangle()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn all() -> Vec<UID> {
|
||||||
|
let mut uids = Primitive::ALL.map(|p| p.mangle()).to_vec();
|
||||||
|
uids.push(nothing());
|
||||||
|
uids
|
||||||
|
}
|
|
@ -1,12 +1,10 @@
|
||||||
pub mod analyzer;
|
pub mod analyzer;
|
||||||
|
mod builtin;
|
||||||
pub mod primitives;
|
pub mod primitives;
|
||||||
|
|
||||||
pub use analyzer::*;
|
|
||||||
pub use primitives::*;
|
pub use primitives::*;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use crate::{BinaryOp, UnaryOp, semantic::Primitive};
|
||||||
|
|
||||||
use crate::{Parameters, Span, err::*, semantic::Primitive};
|
|
||||||
|
|
||||||
pub type UID = String;
|
pub type UID = String;
|
||||||
|
|
||||||
|
@ -15,6 +13,7 @@ pub enum Type {
|
||||||
Ambiguous,
|
Ambiguous,
|
||||||
Prim(Primitive),
|
Prim(Primitive),
|
||||||
Nothing,
|
Nothing,
|
||||||
|
Never,
|
||||||
Struct(UID),
|
Struct(UID),
|
||||||
Function(UID),
|
Function(UID),
|
||||||
}
|
}
|
||||||
|
@ -27,331 +26,50 @@ impl std::fmt::Display for Type {
|
||||||
Type::Nothing => write!(f, "nothing"),
|
Type::Nothing => write!(f, "nothing"),
|
||||||
Type::Struct(s) => write!(f, "struct {s}"),
|
Type::Struct(s) => write!(f, "struct {s}"),
|
||||||
Type::Function(func) => write!(f, "func {func}"),
|
Type::Function(func) => write!(f, "func {func}"),
|
||||||
|
Type::Never => write!(f, "never"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum SymbolKind {
|
pub struct IrBlock {
|
||||||
Variable {
|
nodes: Vec<IrNode>,
|
||||||
type_: UID,
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum IrNode {
|
||||||
|
Declaration {
|
||||||
|
uid: UID,
|
||||||
mutable: bool,
|
mutable: bool,
|
||||||
global: bool,
|
size: usize,
|
||||||
children: Vec<UID>,
|
value: IrExpr,
|
||||||
},
|
},
|
||||||
Function {
|
Function {
|
||||||
params: Parameters,
|
uid: UID,
|
||||||
returns: UID,
|
parameters: Vec<Type>,
|
||||||
|
block: IrBlock,
|
||||||
},
|
},
|
||||||
Struct {
|
Conditional {
|
||||||
params: Parameters,
|
branches: Vec<(IrExpr, IrBlock)>,
|
||||||
size: usize,
|
default: IrBlock,
|
||||||
align: usize,
|
|
||||||
},
|
},
|
||||||
TypeDef {
|
Expr(IrExpr),
|
||||||
actual: Type,
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum IrExpr {
|
||||||
|
Ident(UID),
|
||||||
|
UnOp {
|
||||||
|
op: UnaryOp,
|
||||||
|
child: Box<IrExpr>,
|
||||||
|
},
|
||||||
|
BinOp {
|
||||||
|
op: BinaryOp,
|
||||||
|
left: Box<IrExpr>,
|
||||||
|
right: Box<IrExpr>,
|
||||||
|
},
|
||||||
|
Call {
|
||||||
|
function: UID,
|
||||||
|
args: Vec<IrExpr>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Symbol {
|
|
||||||
pub name: String,
|
|
||||||
pub uid: UID,
|
|
||||||
pub span: Option<Span>,
|
|
||||||
pub kind: SymbolKind,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Symbol {
|
|
||||||
pub fn is_variable(&self) -> Result<()> {
|
|
||||||
let name = &self.name;
|
|
||||||
match &self.kind {
|
|
||||||
SymbolKind::Variable { .. } => Ok(()),
|
|
||||||
SymbolKind::Function { .. } => {
|
|
||||||
error().reason(format!("'{name}' refers to a function, not a value"))
|
|
||||||
},
|
|
||||||
_ => error().reason(format!("'{name}' refers to a type, not a value")),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_type(&self) -> Result<Type> {
|
|
||||||
let name = &self.name;
|
|
||||||
match &self.kind {
|
|
||||||
SymbolKind::Struct { .. } => Ok(Type::Struct(self.uid.clone())),
|
|
||||||
SymbolKind::TypeDef { actual } => Ok(actual.clone()),
|
|
||||||
_ => error().reason(format!("'{name}' refers to a value, not a type")),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub enum Event {
|
|
||||||
Declared { name: String, uid: UID },
|
|
||||||
Moved { name: String, uid: UID, span: Span },
|
|
||||||
Func { returns: Vec<UID>, uid: UID },
|
|
||||||
Block { returns: UID },
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct SymbolTable {
|
|
||||||
syms: HashMap<UID, Symbol>,
|
|
||||||
scope: Vec<Event>,
|
|
||||||
nesting: usize,
|
|
||||||
mangle_num: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SymbolTable {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
syms: HashMap::new(),
|
|
||||||
scope: vec![],
|
|
||||||
nesting: 0,
|
|
||||||
mangle_num: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn generate_uid(&mut self, name: &str) -> UID {
|
|
||||||
let uid = format!("${}${name}", self.mangle_num);
|
|
||||||
self.mangle_num += 1;
|
|
||||||
uid
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get(&self, uid: &UID) -> &Symbol {
|
|
||||||
self.syms.get(uid).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_mut(&mut self, uid: &UID) -> &mut Symbol {
|
|
||||||
self.syms.get_mut(uid).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the definition of a symbol in local and global scope
|
|
||||||
pub fn find(&self, name: &str) -> Result<&Symbol> {
|
|
||||||
let mut nesting = self.nesting;
|
|
||||||
for e in self.scope.iter().rev() {
|
|
||||||
match e {
|
|
||||||
Event::Declared { uid, .. }
|
|
||||||
if nesting == self.nesting || nesting == 0 =>
|
|
||||||
{
|
|
||||||
return Ok(self.get(uid));
|
|
||||||
},
|
|
||||||
Event::Moved { name, span, .. }
|
|
||||||
if nesting == self.nesting || nesting == 0 =>
|
|
||||||
{
|
|
||||||
return error()
|
|
||||||
.reason(format!("Symbol '{name}' moved out of scope here"))
|
|
||||||
.span(&span);
|
|
||||||
},
|
|
||||||
Event::Func { .. } => {
|
|
||||||
nesting -= 1;
|
|
||||||
},
|
|
||||||
_ => {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
error().reason(format!("Cannot find symbol '{name}'"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get all nested members of a struct variable
|
|
||||||
fn get_all_children(&self, uid: &UID) -> Vec<UID> {
|
|
||||||
use SymbolKind as s;
|
|
||||||
match &self.get(uid).kind {
|
|
||||||
s::Variable { children, .. } => {
|
|
||||||
let mut new_children = children.clone();
|
|
||||||
for uid in children {
|
|
||||||
new_children.append(&mut self.get_all_children(uid))
|
|
||||||
}
|
|
||||||
new_children
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
vec![]
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move a symbol out of scope
|
|
||||||
pub fn move_symbol(&mut self, move_uid: &UID, span: Span) -> Result<()> {
|
|
||||||
if let SymbolKind::Variable { global, .. } = self.get(move_uid).kind {
|
|
||||||
if global {
|
|
||||||
return error().reason("Cannot move global symbol").span(&span);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
panic!("Moved non-variable {move_uid}");
|
|
||||||
}
|
|
||||||
let children = self.get_all_children(move_uid);
|
|
||||||
for e in self.scope.iter().rev() {
|
|
||||||
match e {
|
|
||||||
Event::Declared { uid, .. } => {
|
|
||||||
if move_uid == uid {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Event::Moved { uid, span, .. } => {
|
|
||||||
if children.contains(uid) {
|
|
||||||
return error()
|
|
||||||
.reason("Symbol was partially moved here")
|
|
||||||
.span(&span);
|
|
||||||
} else if move_uid == uid {
|
|
||||||
return error()
|
|
||||||
.reason("Symbol was previously moved here")
|
|
||||||
.span(&span);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => {},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.scope.push(Event::Moved {
|
|
||||||
name: self.get(move_uid).name.clone(),
|
|
||||||
uid: move_uid.clone(),
|
|
||||||
span,
|
|
||||||
});
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn in_global_scope(&self) -> bool {
|
|
||||||
for e in self.scope.iter().rev() {
|
|
||||||
if let Event::Func { .. } = e {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn define_var(
|
|
||||||
&mut self,
|
|
||||||
name: &str,
|
|
||||||
mutable: bool,
|
|
||||||
type_: &UID,
|
|
||||||
span: Span,
|
|
||||||
) -> UID {
|
|
||||||
let uid = self.generate_uid(name);
|
|
||||||
self.syms.insert(uid.clone(), Symbol {
|
|
||||||
name: name.to_string(),
|
|
||||||
span: Some(span),
|
|
||||||
uid: uid.clone(),
|
|
||||||
kind: SymbolKind::Variable {
|
|
||||||
type_: type_.clone(),
|
|
||||||
mutable,
|
|
||||||
global: self.in_global_scope(),
|
|
||||||
children: vec![],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
self.scope.push(Event::Declared {
|
|
||||||
name: name.to_string(),
|
|
||||||
uid: uid.clone(),
|
|
||||||
});
|
|
||||||
uid
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn declare_struct(
|
|
||||||
&mut self,
|
|
||||||
struct_name: &str,
|
|
||||||
span: Span,
|
|
||||||
) -> Result<UID> {
|
|
||||||
// Check for multiple definition
|
|
||||||
for e in self.scope.iter().rev() {
|
|
||||||
match e {
|
|
||||||
Event::Declared { name, uid } => {
|
|
||||||
if name == struct_name {
|
|
||||||
let e = error().reason(format!(
|
|
||||||
"Structure '{struct_name}' is defined multiple times"
|
|
||||||
));
|
|
||||||
if let Some(s) = &self.get(uid).span {
|
|
||||||
return e.span(s);
|
|
||||||
} else {
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Event::Moved { .. } => {},
|
|
||||||
_ => break,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let uid = self.generate_uid(struct_name);
|
|
||||||
self.syms.insert(uid.clone(), Symbol {
|
|
||||||
name: struct_name.to_string(),
|
|
||||||
uid: uid.clone(),
|
|
||||||
span: Some(span),
|
|
||||||
kind: SymbolKind::Struct {
|
|
||||||
params: Parameters::default(),
|
|
||||||
size: 0,
|
|
||||||
align: 0,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
self.scope.push(Event::Declared {
|
|
||||||
name: struct_name.to_string(),
|
|
||||||
uid: uid.clone(),
|
|
||||||
});
|
|
||||||
Ok(uid)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn type_params(&mut self, mut params: Parameters) -> Result<Parameters> {
|
|
||||||
for i in 0..params.arity {
|
|
||||||
params.types[i] = self
|
|
||||||
.find(¶ms.type_names[i])
|
|
||||||
.trace(format!(
|
|
||||||
"while resolving type of field '{}'",
|
|
||||||
params.type_names[i]
|
|
||||||
))?
|
|
||||||
.uid
|
|
||||||
.clone();
|
|
||||||
}
|
|
||||||
Ok(params)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn define_function(
|
|
||||||
&mut self,
|
|
||||||
func_name: &str,
|
|
||||||
params: Parameters,
|
|
||||||
returns_str: Option<&str>,
|
|
||||||
span: Span,
|
|
||||||
) -> Result<UID> {
|
|
||||||
// Check for multiple definition
|
|
||||||
for e in self.scope.iter().rev() {
|
|
||||||
match e {
|
|
||||||
Event::Declared { name, uid } => {
|
|
||||||
if name == func_name {
|
|
||||||
let e = error().reason(format!(
|
|
||||||
"Function '{func_name}' is defined multiple times"
|
|
||||||
));
|
|
||||||
if let Some(s) = &self.get(uid).span {
|
|
||||||
return e.span(s);
|
|
||||||
} else {
|
|
||||||
return e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Event::Moved { .. } => {},
|
|
||||||
_ => break,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let uid = self.generate_uid(func_name);
|
|
||||||
// Check types
|
|
||||||
let params = self.type_params(params)?;
|
|
||||||
let returns = {
|
|
||||||
let sym = self.find(returns_str)?;
|
|
||||||
sym.is_type()?;
|
|
||||||
sym.uid.clone()
|
|
||||||
};
|
|
||||||
self.syms.insert(uid.clone(), Symbol {
|
|
||||||
name: func_name.to_string(),
|
|
||||||
uid: uid.clone(),
|
|
||||||
span: Some(span),
|
|
||||||
kind: SymbolKind::Function { params, returns },
|
|
||||||
});
|
|
||||||
self.scope.push(Event::Declared {
|
|
||||||
name: func_name.to_string(),
|
|
||||||
uid: uid.clone(),
|
|
||||||
});
|
|
||||||
Ok(uid)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn define_struct(&mut self, uid: &UID, params: Parameters) -> Result<()> {
|
|
||||||
let params = self.type_params(params)?;
|
|
||||||
if let SymbolKind::Struct {
|
|
||||||
params: old_params, ..
|
|
||||||
} = &mut self.get_mut(uid).kind
|
|
||||||
{
|
|
||||||
*old_params = params;
|
|
||||||
} else {
|
|
||||||
unreachable!("Defined non-existent struct")
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
use crate::{BinaryOp, UnaryOp};
|
use crate::{BinaryOp, UnaryOp};
|
||||||
|
|
||||||
use crate::err::*;
|
use crate::err::*;
|
||||||
use crate::semantic::{Symbol, Type, UID};
|
use crate::semantic::{UID, builtin};
|
||||||
|
|
||||||
|
macro_rules! count {
|
||||||
|
() => (0usize);
|
||||||
|
( $x:tt $($xs:tt)* ) => (1usize + count!($($xs)*));
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! primitives {
|
macro_rules! primitives {
|
||||||
( $($i:ident),* ) => {
|
( $($i:ident),* ) => {
|
||||||
|
@ -14,6 +19,8 @@ macro_rules! primitives {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Primitive {
|
impl Primitive {
|
||||||
|
pub const ALL: [Primitive; count!($($i)*,) - 1] = [$(Primitive::$i),*];
|
||||||
|
|
||||||
pub fn from_string(string: &str) -> Option<Self> {
|
pub fn from_string(string: &str) -> Option<Self> {
|
||||||
match string {
|
match string {
|
||||||
$(stringify!{$i} => Some(Self::$i),)*
|
$(stringify!{$i} => Some(Self::$i),)*
|
||||||
|
@ -23,10 +30,10 @@ macro_rules! primitives {
|
||||||
|
|
||||||
pub fn mangle(&self) -> UID {
|
pub fn mangle(&self) -> UID {
|
||||||
match self {
|
match self {
|
||||||
Primitive::integer_ambiguous => "$$integer_amgibuous".into(),
|
Primitive::integer_ambiguous => builtin::mangle("integer_ambiguous"),
|
||||||
Primitive::real_ambiguous => "$$real_amgibuous".into(),
|
Primitive::real_ambiguous => builtin::mangle("real_ambiguous"),
|
||||||
$(
|
$(
|
||||||
Primitive::$i => format!("$${}", stringify!{$i}),
|
Primitive::$i => builtin::mangle(stringify!{$i}),
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue