diff options
| author | Cody <cody@codyq.dev> | 2023-02-27 11:55:17 -0600 |
|---|---|---|
| committer | Cody <cody@codyq.dev> | 2023-02-27 11:55:17 -0600 |
| commit | 17110bf563c2f57ab4e9e25e977b74df06b8c1ab (patch) | |
| tree | 5f63b6047db1771aee798293c86682ded0ca4fd6 /src/main.rs | |
| parent | ebfd74ddf0ef6372624ea171e06f8460d0e1351b (diff) | |
| download | sloth-17110bf563c2f57ab4e9e25e977b74df06b8c1ab.tar.gz | |
Functions beginnings
Diffstat (limited to 'src/main.rs')
| -rw-r--r-- | src/main.rs | 143 |
1 files changed, 114 insertions, 29 deletions
diff --git a/src/main.rs b/src/main.rs index 4a78e9e..52fd2e7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,52 +12,137 @@ pub mod ast; pub mod interpreter; pub mod lexer; +use std::io::{self, BufRead, Read, Write}; +use std::{env, fs}; + use itertools::Itertools; +use rand::Rng; use crate::ast::parser::AstParser; use crate::ast::AstVisitor; -use crate::interpreter::AstInterpreter; +use crate::interpreter::{AstInterpreter, InternalFunction, Value}; use crate::lexer::Lexer; -const SOURCE: &str = r#" - -val variable = 5 + 6 * 2; - -if variable == 17 { - print "Hello World"; -} +fn main() { + let args = env::args().collect_vec(); -fn fib(n: i32) -> i32 { - if n == 0 || n == 1 { - return n; + if args.len() < 2 { + println!("Sloth programming language interpreter\n"); + println!("Usage: sloth <file>"); + return; } - var grandparent = 0; - var parent = 1; - var me = 0; - - for i in 0..n-1 { - me = parent + grandparent; - grandparent = parent; - parent = me; - } + let source_path = &args[1]; + let Ok(source) = fs::read_to_string(source_path) else { + println!("Error while reading '{source_path}'"); + return; + }; - return me; -} - -print fib(5); - -"#; - -fn main() { - let lexer = Lexer::new("for x in 0..5 {}"); + let lexer = Lexer::new(&source); let tokens = lexer.collect_vec(); let mut parser = AstParser::new(tokens); let ast = parser.parse(); + println!("--- Abstract Syntax Tree ---"); println!("{ast:#?}"); + println!("--- Program Output ---"); let mut interpreter = AstInterpreter::default(); + + // Defining some builtin callables for our interpreter + interpreter.callables.insert( + "print".to_owned(), + Box::new(InternalFunction(&|args| { + use std::fmt::Write; + + let mut buffer = String::new(); + for arg in args { + write!(&mut buffer, "{}", arg); + } + + let mut stdout = io::stdout(); + stdout.lock().write_all(buffer.as_bytes()); + stdout.flush(); + + Value::Nil + })), + ); + + interpreter.callables.insert( + "println".to_owned(), + Box::new(InternalFunction(&|args| { + use std::fmt::Write; + + let mut buffer = String::new(); + for arg in args { + write!(&mut buffer, "{}", arg); + } + writeln!(&mut buffer); + + let mut stdout = io::stdout(); + stdout.lock().write_all(buffer.as_bytes()); + stdout.flush(); + + Value::Nil + })), + ); + + interpreter.callables.insert( + "readln".to_owned(), + Box::new(InternalFunction(&|args| { + let stdin = io::stdin(); + let mut line = String::new(); + stdin + .lock() + .read_line(&mut line) + .expect("Failed to read line from stdin"); + line.pop(); + + Value::String(line) + })), + ); + + interpreter.callables.insert( + "random".to_owned(), + Box::new(InternalFunction(&|args| { + let result = match args { + [] => rand::thread_rng().gen_range(1..=100), + [Value::Number(max)] => rand::thread_rng().gen_range(0..=*max), + [Value::Number(min), Value::Number(max)] => { + rand::thread_rng().gen_range(*min..=*max) + } + _ => panic!("Invalid usage of 'random' function"), + }; + + Value::Number(result) + })), + ); + + interpreter.callables.insert( + "len".to_owned(), + Box::new(InternalFunction(&|args| { + let result = match &args[0] { + Value::String(value) => value.len() as i32, + _ => panic!("Invalid usage of 'len' function"), + }; + + Value::Number(result) + })), + ); + + interpreter.callables.insert( + "parse_int".to_owned(), + Box::new(InternalFunction(&|args| { + let result = match &args[0] { + Value::String(value) => value.parse::<i32>(), + _ => panic!("Invalid usage of 'parse_int' function"), + } + .expect("Provided string was not an intenger"); + + Value::Number(result) + })), + ); + interpreter.interpret(&ast); } |
