beginnings of a type system
This commit is contained in:
parent
6c02fa4438
commit
924e7e2781
4 changed files with 110 additions and 8 deletions
|
@ -64,7 +64,7 @@ pub enum UnaryOperation {
|
|||
pub struct Compiler {
|
||||
code: Vec<Instruction>,
|
||||
data: Vec<Data>,
|
||||
register: Register,
|
||||
registers: [bool; 256],
|
||||
}
|
||||
|
||||
impl Compiler {
|
||||
|
@ -142,9 +142,15 @@ impl Compiler {
|
|||
}
|
||||
|
||||
fn next_register(&mut self) -> Register {
|
||||
let r = self.register;
|
||||
self.register += 1;
|
||||
r
|
||||
let index = self.registers.iter()
|
||||
.position(|b| *b == false)
|
||||
.expect("ran out of registers");
|
||||
self.registers[index] = true;
|
||||
index as u8
|
||||
}
|
||||
|
||||
fn free_register(&mut self, reg: Register) {
|
||||
self.registers[reg as usize] = false;
|
||||
}
|
||||
|
||||
fn push_data(&mut self, data: Data) -> u8 {
|
||||
|
@ -158,7 +164,7 @@ pub fn expr(tree: &parser::Tree) -> Bytecode {
|
|||
let mut compiler = Compiler {
|
||||
code: Vec::new(),
|
||||
data: Vec::new(),
|
||||
register: 0,
|
||||
registers: [false; 256],
|
||||
};
|
||||
let reg = compiler.tree(tree);
|
||||
let mut bytecode = Bytecode {
|
||||
|
|
54
src/main.rs
54
src/main.rs
|
@ -10,6 +10,7 @@ mod compiler;
|
|||
mod runner;
|
||||
|
||||
use runner::Value;
|
||||
use parser::Kind;
|
||||
|
||||
fn test(code: &str) -> Value {
|
||||
let tokens = lexer::lex(code);
|
||||
|
@ -17,13 +18,24 @@ fn test(code: &str) -> Value {
|
|||
.iter()
|
||||
.filter(|(t, _)| *t != lexer::TokenType::Space)
|
||||
.collect();
|
||||
let tree = parser::parse(&mut tokens.iter().peekable(), 0);
|
||||
let tree = parser::expr(&mut tokens.iter().peekable(), 0);
|
||||
let bytecode = compiler::expr(&tree);
|
||||
let result = runner::execute(&bytecode);
|
||||
dbg!(&result);
|
||||
result
|
||||
}
|
||||
|
||||
fn parse_kind(code: &str) -> Kind {
|
||||
let tokens = lexer::lex(code);
|
||||
let tokens: Vec<_> = tokens
|
||||
.iter()
|
||||
.filter(|(t, _)| *t != lexer::TokenType::Space)
|
||||
.collect();
|
||||
let tree = parser::kind(&mut tokens.iter().peekable());
|
||||
dbg!(&tree);
|
||||
tree
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// test("math.sin");
|
||||
// test("math.sin(10 * math.pi)");
|
||||
|
@ -37,7 +49,9 @@ fn main() {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{Value, test};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use super::{Value, Kind, test, parse_kind};
|
||||
|
||||
#[test]
|
||||
fn test_number() {
|
||||
|
@ -93,4 +107,40 @@ mod tests {
|
|||
fn test_let() {
|
||||
// test("let foo = 123");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_kind() {
|
||||
assert_eq!(parse_kind("u8"), Kind::Primitive);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_kind_struct() {
|
||||
let k = Kind::Struct(HashMap::from([
|
||||
("foo".to_owned(), Kind::Primitive),
|
||||
("bar".to_owned(), Kind::Primitive),
|
||||
]));
|
||||
assert_eq!(parse_kind("struct { foo: u8, bar: u8 }"), k);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_kind_struct_trailing_comma() {
|
||||
let k = Kind::Struct(HashMap::from([
|
||||
("foo".to_owned(), Kind::Primitive),
|
||||
("bar".to_owned(), Kind::Primitive),
|
||||
]));
|
||||
assert_eq!(parse_kind("struct { foo: u8, bar: u8, }"), k);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_kind_struct_nested() {
|
||||
let k = Kind::Struct(HashMap::from([
|
||||
("foo".to_owned(), Kind::Primitive),
|
||||
("bar".to_owned(), Kind::Primitive),
|
||||
("baz".to_owned(), Kind::Struct(HashMap::from([
|
||||
("one".to_owned(), Kind::Primitive),
|
||||
("two".to_owned(), Kind::Primitive),
|
||||
]))),
|
||||
]));
|
||||
assert_eq!(parse_kind("struct { foo: u8, bar: u8, baz: struct { one: u8, two: u8 } }"), k);
|
||||
}
|
||||
}
|
||||
|
|
41
src/parser/kind.rs
Normal file
41
src/parser/kind.rs
Normal file
|
@ -0,0 +1,41 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use crate::lexer;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum Kind {
|
||||
Primitive,
|
||||
Struct(HashMap<String, Kind>),
|
||||
}
|
||||
|
||||
pub fn parse(tokens: &mut std::iter::Peekable<std::slice::Iter<&(lexer::TokenType, &str)>>) -> Kind {
|
||||
match tokens.next().expect("missing token") {
|
||||
(_, "u8") => Kind::Primitive,
|
||||
(_, "struct") => {
|
||||
let mut kv = HashMap::new();
|
||||
let (lexer::TokenType::Paran, "{") = tokens.next().expect("missing token") else {
|
||||
panic!("expected {{");
|
||||
};
|
||||
loop {
|
||||
let (lexer::TokenType::Ident, name) = tokens.peek().expect("missing token") else {
|
||||
break;
|
||||
};
|
||||
tokens.next();
|
||||
let (lexer::TokenType::Symbol, ":") = tokens.next().expect("missing token") else {
|
||||
panic!("expected colon");
|
||||
};
|
||||
let kind = parse(tokens);
|
||||
kv.insert(name.to_string(), kind);
|
||||
let (lexer::TokenType::Symbol, ",") = tokens.peek().expect("missing token") else {
|
||||
break;
|
||||
};
|
||||
tokens.next();
|
||||
};
|
||||
let (lexer::TokenType::Paran, "}") = tokens.next().expect("missing token") else {
|
||||
panic!("expected }}");
|
||||
};
|
||||
Kind::Struct(kv)
|
||||
},
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
|
@ -1,6 +1,11 @@
|
|||
mod expr;
|
||||
mod kind;
|
||||
|
||||
pub use expr::{
|
||||
UnaryOpType, BinaryOpType, TernaryOpType,
|
||||
parse, Tree, ParserError,
|
||||
parse as expr, Tree, ParserError,
|
||||
};
|
||||
|
||||
pub use kind::{
|
||||
parse as kind, Kind,
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue