Laptop changes
This commit is contained in:
parent
1ab6bb1e2b
commit
c5eed8dcf8
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -40,6 +40,7 @@ dependencies = [
|
||||||
name = "lang"
|
name = "lang"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"punycode",
|
||||||
"wat",
|
"wat",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -55,6 +56,12 @@ version = "2.7.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "punycode"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e9e1dcb320d6839f6edb64f7a4a59d39b30480d4d1765b56873f7c858538a5fe"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-width"
|
name = "unicode-width"
|
||||||
version = "0.1.14"
|
version = "0.1.14"
|
||||||
|
|
|
@ -5,3 +5,4 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wat = "1.219"
|
wat = "1.219"
|
||||||
|
punycode = "0.4"
|
||||||
|
|
|
@ -78,5 +78,7 @@ fn main() -> Result<()> {
|
||||||
*/
|
*/
|
||||||
//let module = frontend::Module::from_file("./demo.hal")?;
|
//let module = frontend::Module::from_file("./demo.hal")?;
|
||||||
//module.write_to("test");
|
//module.write_to("test");
|
||||||
|
let p = punycode::encode("-_").unwrap();
|
||||||
|
println!("{p}");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{Base, semantic::*};
|
use crate::Base;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -45,7 +45,6 @@ pub enum ExpressionKind {
|
||||||
Immediate(Immediate),
|
Immediate(Immediate),
|
||||||
Identifier {
|
Identifier {
|
||||||
name: String,
|
name: String,
|
||||||
uid: UID,
|
|
||||||
},
|
},
|
||||||
Binary {
|
Binary {
|
||||||
op: BinaryOp,
|
op: BinaryOp,
|
||||||
|
@ -60,25 +59,20 @@ pub enum ExpressionKind {
|
||||||
FunctionDef {
|
FunctionDef {
|
||||||
params: Parameters,
|
params: Parameters,
|
||||||
returns_str: Option<String>,
|
returns_str: Option<String>,
|
||||||
returns_actual: Type,
|
|
||||||
body: Vec<Statement>,
|
body: Vec<Statement>,
|
||||||
uid: UID,
|
|
||||||
},
|
},
|
||||||
FunctionCall {
|
FunctionCall {
|
||||||
callee: Box<Expression>,
|
callee: Box<Expression>,
|
||||||
args: Vec<Expression>,
|
args: Vec<Expression>,
|
||||||
uid: UID,
|
|
||||||
},
|
},
|
||||||
StructDef(Parameters, UID),
|
StructDef(Parameters),
|
||||||
StructLiteral {
|
StructLiteral {
|
||||||
name: String,
|
name: String,
|
||||||
args: Vec<(String, Expression)>,
|
args: Vec<(String, Expression)>,
|
||||||
uid: UID,
|
|
||||||
},
|
},
|
||||||
Field {
|
Field {
|
||||||
namespace: Box<Expression>,
|
namespace: Box<Expression>,
|
||||||
field: Box<Expression>,
|
field: Box<Expression>,
|
||||||
uid: UID,
|
|
||||||
},
|
},
|
||||||
Block(Vec<Statement>),
|
Block(Vec<Statement>),
|
||||||
If {
|
If {
|
||||||
|
@ -92,16 +86,11 @@ pub enum ExpressionKind {
|
||||||
pub struct Expression {
|
pub struct Expression {
|
||||||
pub kind: ExpressionKind,
|
pub kind: ExpressionKind,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub type_: UID,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Expression {
|
impl Expression {
|
||||||
pub fn new(kind: ExpressionKind, span: Span) -> Self {
|
pub fn new(kind: ExpressionKind, span: Span) -> Self {
|
||||||
Self {
|
Self { kind, span }
|
||||||
kind,
|
|
||||||
span,
|
|
||||||
type_: "".into(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,28 +105,28 @@ impl std::fmt::Display for ExpressionKind {
|
||||||
right,
|
right,
|
||||||
} => {
|
} => {
|
||||||
write!(f, "({left} {token} {right})")
|
write!(f, "({left} {token} {right})")
|
||||||
},
|
}
|
||||||
e::Parenthesis(inner) => write!(f, "{inner}"),
|
e::Parenthesis(inner) => write!(f, "{inner}"),
|
||||||
e::Unary { op: token, child } => {
|
e::Unary { op: token, child } => {
|
||||||
write!(f, "({token} {child})")
|
write!(f, "({token} {child})")
|
||||||
},
|
}
|
||||||
e::Identifier { name, .. } => write!(f, "{name}"),
|
e::Identifier { name, .. } => write!(f, "{name}"),
|
||||||
e::FunctionCall { callee, args, .. } => {
|
e::FunctionCall { callee, args, .. } => {
|
||||||
write!(f, "({callee} call {args:?})")
|
write!(f, "({callee} call {args:?})")
|
||||||
},
|
}
|
||||||
e::Field {
|
e::Field {
|
||||||
namespace, field, ..
|
namespace, field, ..
|
||||||
} => {
|
} => {
|
||||||
write!(f, "({namespace} . {field})")
|
write!(f, "({namespace} . {field})")
|
||||||
},
|
}
|
||||||
e::FunctionDef {
|
e::FunctionDef {
|
||||||
params,
|
params,
|
||||||
returns_actual,
|
returns_str,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
write!(f, "(fn({params:?}) -> {returns_actual})")
|
write!(f, "(fn({params:?}) -> {returns_str:?})")
|
||||||
},
|
}
|
||||||
e::StructDef(params, _) => write!(f, "struct {{ {params:?} }}"),
|
e::StructDef(params) => write!(f, "struct {{ {params:?} }}"),
|
||||||
e::StructLiteral { name, args, .. } => write!(f, "{name} {{ {args:?} }}"),
|
e::StructLiteral { name, args, .. } => write!(f, "{name} {{ {args:?} }}"),
|
||||||
e::Block(block) => {
|
e::Block(block) => {
|
||||||
write!(f, "{{\n")?;
|
write!(f, "{{\n")?;
|
||||||
|
@ -145,12 +134,8 @@ impl std::fmt::Display for ExpressionKind {
|
||||||
write!(f, "{:#?}", s)?;
|
write!(f, "{:#?}", s)?;
|
||||||
}
|
}
|
||||||
write!(f, "}}")
|
write!(f, "}}")
|
||||||
},
|
}
|
||||||
e::If {
|
e::If { block, else_, .. } => {
|
||||||
predicate,
|
|
||||||
block,
|
|
||||||
else_,
|
|
||||||
} => {
|
|
||||||
write!(f, "{{\n")?;
|
write!(f, "{{\n")?;
|
||||||
for s in block {
|
for s in block {
|
||||||
write!(f, "{:#?}", s)?;
|
write!(f, "{:#?}", s)?;
|
||||||
|
@ -160,14 +145,14 @@ impl std::fmt::Display for ExpressionKind {
|
||||||
write!(f, "{else_}")?;
|
write!(f, "{else_}")?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for Expression {
|
impl std::fmt::Display for Expression {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "({} {})", self.kind, self.type_)
|
write!(f, "({})", self.kind)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,7 +227,6 @@ impl<I: Iterator<Item = Token>> Parser<I> {
|
||||||
e::Field {
|
e::Field {
|
||||||
namespace: current.into(),
|
namespace: current.into(),
|
||||||
field: field.into(),
|
field: field.into(),
|
||||||
uid: "".into(),
|
|
||||||
},
|
},
|
||||||
span,
|
span,
|
||||||
)
|
)
|
||||||
|
@ -259,7 +243,7 @@ impl<I: Iterator<Item = Token>> Parser<I> {
|
||||||
Ok(a) => {
|
Ok(a) => {
|
||||||
span = span + a.span;
|
span = span + a.span;
|
||||||
args.push(a)
|
args.push(a)
|
||||||
},
|
}
|
||||||
Err(_) => break,
|
Err(_) => break,
|
||||||
};
|
};
|
||||||
if !self.eat(t::Comma).is_ok() {
|
if !self.eat(t::Comma).is_ok() {
|
||||||
|
@ -271,7 +255,6 @@ impl<I: Iterator<Item = Token>> Parser<I> {
|
||||||
e::FunctionCall {
|
e::FunctionCall {
|
||||||
callee: current.into(),
|
callee: current.into(),
|
||||||
args,
|
args,
|
||||||
uid: "".into(),
|
|
||||||
},
|
},
|
||||||
span + span2,
|
span + span2,
|
||||||
);
|
);
|
||||||
|
@ -319,10 +302,9 @@ impl<I: Iterator<Item = Token>> Parser<I> {
|
||||||
names.push(name.clone());
|
names.push(name.clone());
|
||||||
// Param type (optional)
|
// Param type (optional)
|
||||||
if self.eat(t::Colon).is_ok() {
|
if self.eat(t::Colon).is_ok() {
|
||||||
let (type_name, span2) = self.identifier().trace_span(
|
let (type_name, span2) = self
|
||||||
span + span2,
|
.identifier()
|
||||||
format!("While parsing type of '{}'", name),
|
.trace_span(span + span2, format!("While parsing type of '{}'", name))?;
|
||||||
)?;
|
|
||||||
strongly_typed = true;
|
strongly_typed = true;
|
||||||
span = span + span2;
|
span = span + span2;
|
||||||
type_names.push(type_name);
|
type_names.push(type_name);
|
||||||
|
@ -376,38 +358,37 @@ impl<I: Iterator<Item = Token>> Parser<I> {
|
||||||
t::IntegerLiteral(i, b) => {
|
t::IntegerLiteral(i, b) => {
|
||||||
self.skip(1);
|
self.skip(1);
|
||||||
e::Immediate(im::Integer(i, b))
|
e::Immediate(im::Integer(i, b))
|
||||||
},
|
}
|
||||||
t::FloatLiteral(f) => {
|
t::FloatLiteral(f) => {
|
||||||
self.skip(1);
|
self.skip(1);
|
||||||
e::Immediate(im::Real(f))
|
e::Immediate(im::Real(f))
|
||||||
},
|
}
|
||||||
t::StringLiteral(s) => {
|
t::StringLiteral(s) => {
|
||||||
self.skip(1);
|
self.skip(1);
|
||||||
e::Immediate(im::String(s))
|
e::Immediate(im::String(s))
|
||||||
},
|
}
|
||||||
t::GlyphLiteral(c) => {
|
t::GlyphLiteral(c) => {
|
||||||
self.skip(1);
|
self.skip(1);
|
||||||
e::Immediate(im::Glyph(c))
|
e::Immediate(im::Glyph(c))
|
||||||
},
|
}
|
||||||
t::True => {
|
t::True => {
|
||||||
self.skip(1);
|
self.skip(1);
|
||||||
e::Immediate(im::Boolean(true))
|
e::Immediate(im::Boolean(true))
|
||||||
},
|
}
|
||||||
t::False => {
|
t::False => {
|
||||||
self.skip(1);
|
self.skip(1);
|
||||||
e::Immediate(im::Boolean(false))
|
e::Immediate(im::Boolean(false))
|
||||||
},
|
}
|
||||||
t::If => return self.if_else(),
|
t::If => return self.if_else(),
|
||||||
t::LeftBrace => {
|
t::LeftBrace => {
|
||||||
let (block, span1) = self.block()?;
|
let (block, span1) = self.block()?;
|
||||||
span = span + span1;
|
span = span + span1;
|
||||||
e::Block(block)
|
e::Block(block)
|
||||||
},
|
}
|
||||||
// Function definition
|
// Function definition
|
||||||
t::LeftParen
|
t::LeftParen
|
||||||
if (self.look(1, t::Identifier("".into())).is_ok()
|
if (self.look(1, t::Identifier("".into())).is_ok()
|
||||||
&& (self.look(2, t::Colon).is_ok()
|
&& (self.look(2, t::Colon).is_ok() || self.look(2, t::Comma).is_ok()))
|
||||||
|| self.look(2, t::Comma).is_ok()))
|
|
||||||
|| self.look(1, t::RightParen).is_ok() =>
|
|| self.look(1, t::RightParen).is_ok() =>
|
||||||
{
|
{
|
||||||
self.skip(1);
|
self.skip(1);
|
||||||
|
@ -434,19 +415,17 @@ impl<I: Iterator<Item = Token>> Parser<I> {
|
||||||
e::FunctionDef {
|
e::FunctionDef {
|
||||||
params,
|
params,
|
||||||
returns_str,
|
returns_str,
|
||||||
returns_actual: Type::Ambiguous,
|
|
||||||
body,
|
body,
|
||||||
uid: "".into(),
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
// Struct definition
|
// Struct definition
|
||||||
t::Struct => {
|
t::Struct => {
|
||||||
self.skip(1);
|
self.skip(1);
|
||||||
self.eat(t::LeftBrace)?;
|
self.eat(t::LeftBrace)?;
|
||||||
let params = self.parameters(span)?;
|
let params = self.parameters(span)?;
|
||||||
self.eat(t::RightBrace)?;
|
self.eat(t::RightBrace)?;
|
||||||
e::StructDef(params, "".into())
|
e::StructDef(params)
|
||||||
},
|
}
|
||||||
// Struct literal
|
// Struct literal
|
||||||
t::Identifier(name) if self.look(1, t::LeftBrace).is_ok() => {
|
t::Identifier(name) if self.look(1, t::LeftBrace).is_ok() => {
|
||||||
self.skip(2);
|
self.skip(2);
|
||||||
|
@ -470,19 +449,12 @@ impl<I: Iterator<Item = Token>> Parser<I> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.eat(t::RightBrace)?;
|
self.eat(t::RightBrace)?;
|
||||||
e::StructLiteral {
|
e::StructLiteral { name, args }
|
||||||
name,
|
}
|
||||||
args,
|
|
||||||
uid: "".into(),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
t::Identifier(i) => {
|
t::Identifier(i) => {
|
||||||
self.skip(1);
|
self.skip(1);
|
||||||
e::Identifier {
|
e::Identifier { name: i }
|
||||||
name: i,
|
}
|
||||||
uid: "".into(),
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// Parenthetical
|
// Parenthetical
|
||||||
t::LeftParen => {
|
t::LeftParen => {
|
||||||
self.skip(1);
|
self.skip(1);
|
||||||
|
@ -494,12 +466,12 @@ impl<I: Iterator<Item = Token>> Parser<I> {
|
||||||
.reason("Unclosed '('")
|
.reason("Unclosed '('")
|
||||||
.span(&expr.span)?;
|
.span(&expr.span)?;
|
||||||
e::Parenthesis(expr.into())
|
e::Parenthesis(expr.into())
|
||||||
},
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return error()
|
return error()
|
||||||
.span(&span)
|
.span(&span)
|
||||||
.reason(format!("Expected expression, found {}", next.0));
|
.reason(format!("Expected expression, found {}", next.0));
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
Ok(Expression::new(kind, span))
|
Ok(Expression::new(kind, span))
|
||||||
}
|
}
|
||||||
|
@ -540,7 +512,7 @@ impl<I: Iterator<Item = Token>> Parser<I> {
|
||||||
Ok(Token(t::Identifier(i), span)) => {
|
Ok(Token(t::Identifier(i), span)) => {
|
||||||
self.skip(1);
|
self.skip(1);
|
||||||
Ok((i, span))
|
Ok((i, span))
|
||||||
},
|
}
|
||||||
Ok(t) => error()
|
Ok(t) => error()
|
||||||
.reason(format!("Expected identifier, found {}", t.0))
|
.reason(format!("Expected identifier, found {}", t.0))
|
||||||
.span(&t.1),
|
.span(&t.1),
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
use crate::semantic::UID;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -47,7 +45,7 @@ impl<I: Iterator<Item = Token>> Parser<I> {
|
||||||
Ok(Token(t::Identifier(s), span2)) => {
|
Ok(Token(t::Identifier(s), span2)) => {
|
||||||
span = span + span2;
|
span = span + span2;
|
||||||
Some(s)
|
Some(s)
|
||||||
},
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
let mutable = if self.eat(t::Equal).is_ok() {
|
let mutable = if self.eat(t::Equal).is_ok() {
|
||||||
|
@ -63,14 +61,13 @@ impl<I: Iterator<Item = Token>> Parser<I> {
|
||||||
.expression(0)
|
.expression(0)
|
||||||
.trace_span(span, "while parsing declaration")?;
|
.trace_span(span, "while parsing declaration")?;
|
||||||
span = span + value.span;
|
span = span + value.span;
|
||||||
let no_semicolon =
|
let no_semicolon = if let ExpressionKind::FunctionDef { .. } = value.kind {
|
||||||
if let ExpressionKind::FunctionDef { .. } = value.kind {
|
true
|
||||||
true
|
} else if let ExpressionKind::StructDef(_) = value.kind {
|
||||||
} else if let ExpressionKind::StructDef(_, _) = value.kind {
|
true
|
||||||
true
|
} else {
|
||||||
} else {
|
false
|
||||||
false
|
};
|
||||||
};
|
|
||||||
let s = Statement {
|
let s = Statement {
|
||||||
kind: s::Declaration {
|
kind: s::Declaration {
|
||||||
name,
|
name,
|
||||||
|
@ -84,7 +81,7 @@ impl<I: Iterator<Item = Token>> Parser<I> {
|
||||||
return Ok(s);
|
return Ok(s);
|
||||||
}
|
}
|
||||||
s
|
s
|
||||||
},
|
}
|
||||||
// Assignment
|
// Assignment
|
||||||
(Token(t::Identifier(name), span2), Ok(Token(t::Equal, span3))) => {
|
(Token(t::Identifier(name), span2), Ok(Token(t::Equal, span3))) => {
|
||||||
self.skip(2);
|
self.skip(2);
|
||||||
|
@ -96,7 +93,7 @@ impl<I: Iterator<Item = Token>> Parser<I> {
|
||||||
span,
|
span,
|
||||||
kind: s::Assignment { name, value },
|
kind: s::Assignment { name, value },
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
// While
|
// While
|
||||||
(Token(t::While, span2), _) => {
|
(Token(t::While, span2), _) => {
|
||||||
self.skip(1);
|
self.skip(1);
|
||||||
|
@ -117,7 +114,7 @@ impl<I: Iterator<Item = Token>> Parser<I> {
|
||||||
block: block.0,
|
block: block.0,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
// (DEBUG) print
|
// (DEBUG) print
|
||||||
(Token(t::Print, span2), _) => {
|
(Token(t::Print, span2), _) => {
|
||||||
self.skip(1);
|
self.skip(1);
|
||||||
|
@ -130,7 +127,7 @@ impl<I: Iterator<Item = Token>> Parser<I> {
|
||||||
span,
|
span,
|
||||||
kind: s::Print(expr),
|
kind: s::Print(expr),
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
// Return
|
// Return
|
||||||
(Token(t::Return, span2), _) => {
|
(Token(t::Return, span2), _) => {
|
||||||
span = span + span2;
|
span = span + span2;
|
||||||
|
@ -143,7 +140,7 @@ impl<I: Iterator<Item = Token>> Parser<I> {
|
||||||
span,
|
span,
|
||||||
kind: s::Return(expr),
|
kind: s::Return(expr),
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
// Expression
|
// Expression
|
||||||
(Token(_, span2), _) => {
|
(Token(_, span2), _) => {
|
||||||
span = span + span2;
|
span = span + span2;
|
||||||
|
@ -165,14 +162,14 @@ impl<I: Iterator<Item = Token>> Parser<I> {
|
||||||
span,
|
span,
|
||||||
kind: s::Expression(expr),
|
kind: s::Expression(expr),
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
_ => Statement {
|
_ => Statement {
|
||||||
span,
|
span,
|
||||||
kind: s::Expression(expr),
|
kind: s::Expression(expr),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
// Check for semicolon
|
// Check for semicolon
|
||||||
if self.eat(t::Semicolon).is_ok() {
|
if self.eat(t::Semicolon).is_ok() {
|
||||||
|
|
|
@ -1,3 +1,53 @@
|
||||||
use crate::{Expression, ExpressionKind, Statement, StatementKind};
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::{err::*, Expression, ExpressionKind, Statement, StatementKind};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use ir::*;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
enum Undo {
|
||||||
|
FuncGuard,
|
||||||
|
BlockGuard,
|
||||||
|
Symbol { name: String, prev: Vec<Symbol> },
|
||||||
|
Push { name: String },
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct Symbol {
|
||||||
|
mangle: SID,
|
||||||
|
type_: TID,
|
||||||
|
life: Lifetime,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct SymbolTable {
|
||||||
|
types: HashMap<TID, Type>,
|
||||||
|
table: HashMap<String, Vec<Symbol>>,
|
||||||
|
undo_stack: Vec<Undo>,
|
||||||
|
path: Vec<String>,
|
||||||
|
salt: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SymbolTable {
|
||||||
|
fn define(&mut self, name: &str, type_: TID, life: Lifetime) {
|
||||||
|
if !self.table.contains_key(name) {
|
||||||
|
self.table.insert(name.to_string(), vec![]);
|
||||||
|
}
|
||||||
|
let symbols = self.table.get_mut(name).unwrap();
|
||||||
|
let mut path = self.path.clone();
|
||||||
|
path.push(name.to_string());
|
||||||
|
let mangle = names::mangle(path, &format!("{:#x}", self.salt));
|
||||||
|
let symbol = Symbol {
|
||||||
|
mangle,
|
||||||
|
type_,
|
||||||
|
life,
|
||||||
|
};
|
||||||
|
let undo = if
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn analyze_block(stmts: Vec<Statement>) -> Result<Vec<IrNode>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
use super::{UID, primitives::Primitive};
|
use super::{primitives::Primitive, SID};
|
||||||
|
|
||||||
pub fn mangle(input: &str) -> UID {
|
pub fn mangle(input: &str) -> SID {
|
||||||
format!("$${input}")
|
format!("$B${input}")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nothing ever happens
|
// Nothing ever happens
|
||||||
pub fn nothing() -> UID {
|
pub fn nothing() -> SID {
|
||||||
mangle("nothing")
|
mangle("nothing")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn integer() -> UID {
|
pub fn integer() -> SID {
|
||||||
Primitive::integer_ambiguous.mangle()
|
Primitive::integer_ambiguous.mangle()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn real() -> UID {
|
pub fn real() -> SID {
|
||||||
Primitive::real_ambiguous.mangle()
|
Primitive::real_ambiguous.mangle()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn all() -> Vec<UID> {
|
pub fn all() -> Vec<SID> {
|
||||||
let mut uids = Primitive::ALL.map(|p| p.mangle()).to_vec();
|
let mut uids = Primitive::ALL.map(|p| p.mangle()).to_vec();
|
||||||
uids.push(nothing());
|
uids.push(nothing());
|
||||||
uids
|
uids
|
||||||
|
|
53
src/semantic/ir.rs
Normal file
53
src/semantic/ir.rs
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
use crate::{BinaryOp, UnaryOp};
|
||||||
|
|
||||||
|
use super::{Type, SID, TID};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct IrBlock {
|
||||||
|
nodes: Vec<IrNode>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum IrNode {
|
||||||
|
Declaration {
|
||||||
|
uid: SID,
|
||||||
|
mutable: bool,
|
||||||
|
size: usize,
|
||||||
|
value: IrExpr,
|
||||||
|
},
|
||||||
|
Function {
|
||||||
|
uid: SID,
|
||||||
|
parameters: Vec<Type>,
|
||||||
|
block: IrBlock,
|
||||||
|
},
|
||||||
|
Conditional {
|
||||||
|
branches: Vec<(IrExpr, IrBlock)>,
|
||||||
|
default: IrBlock,
|
||||||
|
},
|
||||||
|
Expr(IrExpr),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct IrExpr {
|
||||||
|
kind: IrExprKind,
|
||||||
|
type_: TID,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum IrExprKind {
|
||||||
|
Ident(SID),
|
||||||
|
UnOp {
|
||||||
|
op: UnaryOp,
|
||||||
|
child: Box<IrExpr>,
|
||||||
|
},
|
||||||
|
BinOp {
|
||||||
|
op: BinaryOp,
|
||||||
|
left: Box<IrExpr>,
|
||||||
|
right: Box<IrExpr>,
|
||||||
|
},
|
||||||
|
Block(IrBlock),
|
||||||
|
Call {
|
||||||
|
function: SID,
|
||||||
|
args: Vec<IrExpr>,
|
||||||
|
},
|
||||||
|
}
|
|
@ -1,12 +1,25 @@
|
||||||
pub mod analyzer;
|
pub mod analyzer;
|
||||||
mod builtin;
|
pub mod builtin;
|
||||||
|
pub mod ir;
|
||||||
|
pub mod names;
|
||||||
pub mod primitives;
|
pub mod primitives;
|
||||||
|
|
||||||
pub use primitives::*;
|
pub use primitives::*;
|
||||||
|
|
||||||
use crate::{BinaryOp, UnaryOp, semantic::Primitive};
|
use crate::semantic::Primitive;
|
||||||
|
|
||||||
pub type UID = String;
|
/// Type ID
|
||||||
|
pub type TID = usize;
|
||||||
|
/// Name mangle
|
||||||
|
pub type SID = String;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum Lifetime {
|
||||||
|
/// Exists for lifetime of program
|
||||||
|
Static,
|
||||||
|
/// Exists for lifetime of contained scope
|
||||||
|
Dynamic,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Type {
|
pub enum Type {
|
||||||
|
@ -14,8 +27,18 @@ pub enum Type {
|
||||||
Prim(Primitive),
|
Prim(Primitive),
|
||||||
Nothing,
|
Nothing,
|
||||||
Never,
|
Never,
|
||||||
Struct(UID),
|
Struct {
|
||||||
Function(UID),
|
size: usize,
|
||||||
|
name: String,
|
||||||
|
member_names: Vec<String>,
|
||||||
|
member_types: Vec<TID>,
|
||||||
|
},
|
||||||
|
Alias(TID),
|
||||||
|
Function {
|
||||||
|
name: String,
|
||||||
|
arg_names: Vec<String>,
|
||||||
|
arg_types: Vec<TID>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for Type {
|
impl std::fmt::Display for Type {
|
||||||
|
@ -24,52 +47,10 @@ impl std::fmt::Display for Type {
|
||||||
Type::Ambiguous => write!(f, "ambiguous"),
|
Type::Ambiguous => write!(f, "ambiguous"),
|
||||||
Type::Prim(primitive) => write!(f, "{primitive}"),
|
Type::Prim(primitive) => write!(f, "{primitive}"),
|
||||||
Type::Nothing => write!(f, "nothing"),
|
Type::Nothing => write!(f, "nothing"),
|
||||||
Type::Struct(s) => write!(f, "struct {s}"),
|
|
||||||
Type::Function(func) => write!(f, "func {func}"),
|
|
||||||
Type::Never => write!(f, "never"),
|
Type::Never => write!(f, "never"),
|
||||||
|
Type::Struct { name, .. } => write!(f, "struct {name}"),
|
||||||
|
Type::Alias(tid) => write!(f, "alias ({tid})"),
|
||||||
|
Type::Function { name, .. } => write!(f, "func ({name})"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct IrBlock {
|
|
||||||
nodes: Vec<IrNode>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub enum IrNode {
|
|
||||||
Declaration {
|
|
||||||
uid: UID,
|
|
||||||
mutable: bool,
|
|
||||||
size: usize,
|
|
||||||
value: IrExpr,
|
|
||||||
},
|
|
||||||
Function {
|
|
||||||
uid: UID,
|
|
||||||
parameters: Vec<Type>,
|
|
||||||
block: IrBlock,
|
|
||||||
},
|
|
||||||
Conditional {
|
|
||||||
branches: Vec<(IrExpr, IrBlock)>,
|
|
||||||
default: IrBlock,
|
|
||||||
},
|
|
||||||
Expr(IrExpr),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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>,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
16
src/semantic/names.rs
Normal file
16
src/semantic/names.rs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
// <mangle> ::= "$" <path> <salt>
|
||||||
|
// <path> ::= {<path-element>}*
|
||||||
|
// <path-element> ::= <length> <ident>
|
||||||
|
// <ident> ::= <_a-zA-Z> {<_a-zA-Z0-9>}*
|
||||||
|
// <length> ::= {<0-9>}+
|
||||||
|
// <salt> ::= {<a-zA-Z>}*
|
||||||
|
|
||||||
|
pub fn mangle(path: Vec<String>, salt: &str) -> String {
|
||||||
|
let mut buf: Vec<u8> = vec![];
|
||||||
|
for p in path {
|
||||||
|
let bytes = format!("{}{}", p.len(), punycode::encode(&p).unwrap());
|
||||||
|
buf.extend_from_slice(bytes.as_bytes());
|
||||||
|
}
|
||||||
|
buf.extend_from_slice(salt.as_bytes());
|
||||||
|
String::from_utf8(buf).unwrap()
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::{BinaryOp, UnaryOp};
|
use crate::{BinaryOp, UnaryOp};
|
||||||
|
|
||||||
use crate::err::*;
|
use crate::err::*;
|
||||||
use crate::semantic::{UID, builtin};
|
use crate::semantic::{builtin, SID};
|
||||||
|
|
||||||
macro_rules! count {
|
macro_rules! count {
|
||||||
() => (0usize);
|
() => (0usize);
|
||||||
|
@ -28,7 +28,7 @@ macro_rules! primitives {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mangle(&self) -> UID {
|
pub fn mangle(&self) -> SID {
|
||||||
match self {
|
match self {
|
||||||
Primitive::integer_ambiguous => builtin::mangle("integer_ambiguous"),
|
Primitive::integer_ambiguous => builtin::mangle("integer_ambiguous"),
|
||||||
Primitive::real_ambiguous => builtin::mangle("real_ambiguous"),
|
Primitive::real_ambiguous => builtin::mangle("real_ambiguous"),
|
||||||
|
@ -62,9 +62,7 @@ impl Primitive {
|
||||||
pub fn as_wat(&self) -> &'static str {
|
pub fn as_wat(&self) -> &'static str {
|
||||||
use Primitive::*;
|
use Primitive::*;
|
||||||
match self {
|
match self {
|
||||||
boolean | glyph | w8 | w16 | w32 | whole | i8 | i16 | i32 | integer => {
|
boolean | glyph | w8 | w16 | w32 | whole | i8 | i16 | i32 | integer => "i32",
|
||||||
"i32"
|
|
||||||
},
|
|
||||||
w64 | i64 => "i64",
|
w64 | i64 => "i64",
|
||||||
r32 | real => "f32",
|
r32 | real => "f32",
|
||||||
r64 => "f64",
|
r64 => "f64",
|
||||||
|
@ -128,16 +126,11 @@ impl Primitive {
|
||||||
pub fn coerce(self, expect: Primitive) -> Result<Self> {
|
pub fn coerce(self, expect: Primitive) -> Result<Self> {
|
||||||
use Primitive::*;
|
use Primitive::*;
|
||||||
match (self, expect) {
|
match (self, expect) {
|
||||||
(
|
(integer_ambiguous, a @ (i8 | i16 | i32 | i64 | integer | w8 | w16 | w32 | w64 | whole))
|
||||||
integer_ambiguous,
|
| (a @ (i8 | i16 | i32 | i64 | integer | w8 | w16 | w32 | w64 | whole), integer_ambiguous) => {
|
||||||
a @ (i8 | i16 | i32 | i64 | integer | w8 | w16 | w32 | w64 | whole),
|
Ok(a)
|
||||||
)
|
}
|
||||||
| (
|
(real_ambiguous, a @ (r32 | r64 | real)) | (a @ (r32 | r64 | real), real_ambiguous) => Ok(a),
|
||||||
a @ (i8 | i16 | i32 | i64 | integer | w8 | w16 | w32 | w64 | whole),
|
|
||||||
integer_ambiguous,
|
|
||||||
) => Ok(a),
|
|
||||||
(real_ambiguous, a @ (r32 | r64 | real))
|
|
||||||
| (a @ (r32 | r64 | real), real_ambiguous) => Ok(a),
|
|
||||||
(t1, t2) if t1 == t2 => Ok(t1),
|
(t1, t2) if t1 == t2 => Ok(t1),
|
||||||
_ => error().reason(format!("Cannot coerce '{self}' into '{expect}'")),
|
_ => error().reason(format!("Cannot coerce '{self}' into '{expect}'")),
|
||||||
}
|
}
|
||||||
|
@ -158,11 +151,7 @@ impl Primitive {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn binary_op(
|
pub fn binary_op(mut lhs: Primitive, op: BinaryOp, mut rhs: Primitive) -> Result<Primitive> {
|
||||||
mut lhs: Primitive,
|
|
||||||
op: BinaryOp,
|
|
||||||
mut rhs: Primitive,
|
|
||||||
) -> Result<Primitive> {
|
|
||||||
use Primitive::*;
|
use Primitive::*;
|
||||||
if lhs.is_ambiguous() && !rhs.is_ambiguous() {
|
if lhs.is_ambiguous() && !rhs.is_ambiguous() {
|
||||||
lhs = lhs.coerce(rhs)?;
|
lhs = lhs.coerce(rhs)?;
|
||||||
|
@ -188,8 +177,7 @@ impl Primitive {
|
||||||
pub fn unary_op(op: UnaryOp, child: Primitive) -> Result<Primitive> {
|
pub fn unary_op(op: UnaryOp, child: Primitive) -> Result<Primitive> {
|
||||||
use Primitive::*;
|
use Primitive::*;
|
||||||
use UnaryOp::*;
|
use UnaryOp::*;
|
||||||
let e =
|
let e = error().reason(format!("Unary {} is not defined for {}", op, child));
|
||||||
error().reason(format!("Unary {} is not defined for {}", op, child));
|
|
||||||
match op {
|
match op {
|
||||||
Minus => match child {
|
Minus => match child {
|
||||||
boolean | string | glyph | whole | w8 | w16 | w32 | w64 => e,
|
boolean | string | glyph | whole | w8 | w16 | w32 | w64 => e,
|
||||||
|
|
29
test.wat
29
test.wat
|
@ -1,32 +1,9 @@
|
||||||
(module
|
(module
|
||||||
(func $3$func
|
(global $2$s$0 (mut i32) (i32.const 0))
|
||||||
(param $4$s$0 i32)
|
(global $2$s$1 (mut i32) (i32.const 0))
|
||||||
(param $4$s$1 i32)
|
(global $2$s$2 (mut f32) (f32.const 0))
|
||||||
(param $4$s$2 f32)
|
|
||||||
(param $5$a$0 i32)
|
|
||||||
(result i32 i32 f32 )
|
|
||||||
local.get $4$s$2
|
|
||||||
local.get $4$s$1
|
|
||||||
local.get $4$s$0
|
|
||||||
return
|
|
||||||
)
|
|
||||||
(global $2$s$0 (mut i32))
|
|
||||||
(global $2$s$1 (mut i32))
|
|
||||||
(global $2$s$2 (mut f32))
|
|
||||||
(func $$main
|
(func $$main
|
||||||
(local $$tmp0$0 i32)
|
(local $$tmp0$0 i32)
|
||||||
(local $$tmp1$0 i32)
|
(local $$tmp1$0 i32)
|
||||||
i32.const 2
|
|
||||||
i32.const 1
|
|
||||||
local.set $$tmp0$0
|
|
||||||
i32.const 97
|
|
||||||
local.set $$tmp1$0
|
|
||||||
f32.const 1
|
|
||||||
local.get $$tmp1$0
|
|
||||||
local.get $$tmp0$0
|
|
||||||
call $3$func
|
|
||||||
global.set $2$s$0
|
|
||||||
global.set $2$s$1
|
|
||||||
global.set $2$s$2
|
|
||||||
)
|
)
|
||||||
)
|
)
|
Loading…
Reference in a new issue