aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/compiler.rs77
-rw-r--r--src/main.rs18
-rw-r--r--src/tokenizer.rs8
-rw-r--r--src/vm.rs20
-rw-r--r--tests/simple.tdy11
5 files changed, 107 insertions, 27 deletions
diff --git a/src/compiler.rs b/src/compiler.rs
new file mode 100644
index 0000000..59659f4
--- /dev/null
+++ b/src/compiler.rs
@@ -0,0 +1,77 @@
+use crate::tokenizer::{Token, TokenStream};
+use crate::vm::{Value, Block, Op};
+
+struct Compiler {
+ curr: usize,
+ tokens: TokenStream,
+}
+
+impl Compiler {
+ pub fn new(tokens: TokenStream) -> Self {
+ Self {
+ curr: 0,
+ tokens,
+ }
+ }
+
+ fn error(&self, msg: &str) -> ! {
+ println!("ERROR: {}", msg);
+ panic!();
+ }
+
+ fn peek(&self) -> Token {
+ if self.tokens.len() < self.curr {
+ crate::tokenizer::Token::EOF
+ } else {
+ self.tokens[self.curr].0.clone()
+ }
+ }
+
+ fn eat(&mut self) -> Token {
+ let t = self.peek();
+ self.curr += 1;
+ t
+ }
+
+ fn value(&mut self) -> Value {
+ match self.eat() {
+ Token::Float(f) => { Value::Float(f) },
+ Token::Int(f) => { Value::Int(f) }
+ _ => { self.error("Invalid value.") }
+ }
+ }
+
+ fn expression(&mut self, block: &mut Block) {
+ let a = self.value();
+ block.add(Op::Constant(a));
+
+ loop {
+ println!("{:?}", self.peek());
+ let op = match self.eat() {
+ Token::Plus => Op::Add,
+ Token::Minus => Op::Sub,
+ Token::Star => Op::Mul,
+ Token::Slash => Op::Div,
+ _ => { break; }
+ };
+
+ let b = self.value();
+ block.add(Op::Constant(b));
+ block.add(op);
+ }
+ }
+
+ pub fn compile(&mut self, name: &str) -> Block {
+ let mut block = Block::new(name);
+
+ self.expression(&mut block);
+ block.add(Op::Print);
+ block.add(Op::Return);
+
+ block
+ }
+}
+
+pub fn compile(name: &str, tokens: TokenStream) -> Block {
+ Compiler::new(tokens).compile(name)
+}
diff --git a/src/main.rs b/src/main.rs
index 72fb8a1..c9a7602 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,23 +1,11 @@
mod tokenizer;
mod vm;
+mod compiler;
fn main() {
- /*
let tokens = tokenizer::file_to_tokens("tests/simple.tdy");
- for token in tokens.iter() {
- println!("| {:?}", token);
- }
- */
+ let block = compiler::compile("main", tokens);
- let mut blocks = vm::Block::new("main");
- blocks.add(vm::Op::Constant(vm::Value::Bool(true)));
- blocks.add(vm::Op::Print);
- blocks.add(vm::Op::Constant(vm::Value::Int(123)));
- blocks.add(vm::Op::Constant(vm::Value::Int(123)));
- blocks.add(vm::Op::Add);
- blocks.add(vm::Op::Print);
- blocks.add(vm::Op::Return);
-
- vm::run_block(blocks);
+ vm::run_block(block);
}
diff --git a/src/tokenizer.rs b/src/tokenizer.rs
index efea700..cb2d7b8 100644
--- a/src/tokenizer.rs
+++ b/src/tokenizer.rs
@@ -1,7 +1,7 @@
use std::fs;
use logos::{Logos, Span};
-#[derive(Logos, Debug, PartialEq)]
+#[derive(Logos, Debug, PartialEq, Clone)]
pub enum Token {
#[regex(r"[[:alpha:]][[:alnum:]]*", |lex| lex.slice().to_string())]
Identifier(String),
@@ -94,11 +94,15 @@ pub enum Token {
#[regex(r"[ \t\r]", logos::skip)]
Whitespace,
+ EOF,
+
#[error]
Error,
}
-pub fn file_to_tokens(filename: &str) -> Vec<(Token, Span)> {
+pub type PlacedToken = (Token, Span);
+pub type TokenStream = Vec<PlacedToken>;
+pub fn file_to_tokens(filename: &str) -> TokenStream {
let content = fs::read_to_string(filename).unwrap();
let lexer = Token::lexer(&content);
lexer.spanned().collect()
diff --git a/src/vm.rs b/src/vm.rs
index 6a3ccd3..6b64928 100644
--- a/src/vm.rs
+++ b/src/vm.rs
@@ -112,6 +112,26 @@ impl VM {
}
Op::Mul => {
+ let b = self.stack.pop().unwrap();
+ let a = self.stack.pop().unwrap();
+ match (a, b) {
+ (Value::Float(a), Value::Float(b)) => self.stack.push(Value::Float(b * a)),
+ (Value::Int(a), Value::Int(b)) => self.stack.push(Value::Int(b * a)),
+ _ => unimplemented!("Cannot mul '{:?}' and '{:?}'.", a, b),
+ }
+ }
+
+ Op::Div => {
+ let b = self.stack.pop().unwrap();
+ let a = self.stack.pop().unwrap();
+ match (a, b) {
+ (Value::Float(a), Value::Float(b)) => self.stack.push(Value::Float(b / a)),
+ (Value::Int(a), Value::Int(b)) => self.stack.push(Value::Int(b / a)),
+ _ => unimplemented!("Cannot mul '{:?}' and '{:?}'.", a, b),
+ }
+ }
+
+ Op::Mul => {
todo!();
}
diff --git a/tests/simple.tdy b/tests/simple.tdy
index d962330..d248afd 100644
--- a/tests/simple.tdy
+++ b/tests/simple.tdy
@@ -1,10 +1 @@
-1234
-1234.123
-
-a.b
-
-if abcde {
- a = true
- c++
-}
-b = false
+1 + 1 * 2