From 924e7e27815b58e281524f91455c2e9d4b702d8c Mon Sep 17 00:00:00 2001 From: tezlm Date: Tue, 9 May 2023 14:32:19 -0700 Subject: [PATCH] beginnings of a type system --- src/compiler.rs | 16 +++++++++----- src/main.rs | 54 ++++++++++++++++++++++++++++++++++++++++++++-- src/parser/kind.rs | 41 +++++++++++++++++++++++++++++++++++ src/parser/mod.rs | 7 +++++- 4 files changed, 110 insertions(+), 8 deletions(-) create mode 100644 src/parser/kind.rs diff --git a/src/compiler.rs b/src/compiler.rs index 0c97622..0eb82b8 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -64,7 +64,7 @@ pub enum UnaryOperation { pub struct Compiler { code: Vec, data: Vec, - 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 { diff --git a/src/main.rs b/src/main.rs index 8d9d477..48a0114 100644 --- a/src/main.rs +++ b/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); + } } diff --git a/src/parser/kind.rs b/src/parser/kind.rs new file mode 100644 index 0000000..7a3e295 --- /dev/null +++ b/src/parser/kind.rs @@ -0,0 +1,41 @@ +use std::collections::HashMap; + +use crate::lexer; + +#[derive(Debug, PartialEq, Eq)] +pub enum Kind { + Primitive, + Struct(HashMap), +} + +pub fn parse(tokens: &mut std::iter::Peekable>) -> 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!(), + } +} diff --git a/src/parser/mod.rs b/src/parser/mod.rs index fec7ae9..09095b1 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -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, };