added evaluating, basically just added support for adding and
subtracting
This commit is contained in:
Vendored
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"cSpell.words": ["Peekable"]
|
"cSpell.words": ["binop", "Peekable"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
use std::process;
|
|
||||||
|
|
||||||
use crate::parser::Parser;
|
|
||||||
|
|
||||||
pub fn repl() {
|
|
||||||
// Read-Eval-Print Loop
|
|
||||||
use std::io::{self, Write};
|
|
||||||
|
|
||||||
println!("Welcome to the Riv Lang REPL! Type 'exit' to quit.");
|
|
||||||
|
|
||||||
loop {
|
|
||||||
print!("> ");
|
|
||||||
io::stdout().flush().unwrap();
|
|
||||||
|
|
||||||
let mut input = String::new();
|
|
||||||
io::stdin().read_line(&mut input).unwrap();
|
|
||||||
|
|
||||||
let input = input.trim().to_string();
|
|
||||||
|
|
||||||
if input == "exit" {
|
|
||||||
process::exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
let program = Parser::new(input).produce_ast();
|
|
||||||
|
|
||||||
println!("{:#?}", program);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
pub mod ast;
|
||||||
|
pub mod lexer;
|
||||||
|
pub mod parser;
|
||||||
+34
-4
@@ -1,9 +1,39 @@
|
|||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
use std::process;
|
||||||
|
|
||||||
mod ast;
|
|
||||||
mod frontend;
|
mod frontend;
|
||||||
mod lexer;
|
use frontend::ast;
|
||||||
mod parser;
|
use frontend::lexer;
|
||||||
|
use frontend::parser;
|
||||||
|
|
||||||
|
mod runtime;
|
||||||
|
use runtime::interpreter::evaluate;
|
||||||
|
|
||||||
|
pub fn repl() {
|
||||||
|
// Read-Eval-Print Loop
|
||||||
|
use std::io::{self, Write};
|
||||||
|
|
||||||
|
println!("Welcome to the Riv Lang REPL! Type 'exit' to quit.");
|
||||||
|
|
||||||
|
loop {
|
||||||
|
print!("> ");
|
||||||
|
io::stdout().flush().unwrap();
|
||||||
|
|
||||||
|
let mut input = String::new();
|
||||||
|
io::stdin().read_line(&mut input).unwrap();
|
||||||
|
|
||||||
|
let input = input.trim().to_string();
|
||||||
|
|
||||||
|
if input == "exit" {
|
||||||
|
process::exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
let program = parser::Parser::new(input).produce_ast();
|
||||||
|
|
||||||
|
let result = evaluate(frontend::ast::NodeType::Program(program));
|
||||||
|
println!("{:#?}", result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(clap::Parser)]
|
#[derive(clap::Parser)]
|
||||||
struct CLI {
|
struct CLI {
|
||||||
@@ -20,7 +50,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
let cli = CLI::parse();
|
let cli = CLI::parse();
|
||||||
|
|
||||||
if cli.repl {
|
if cli.repl {
|
||||||
frontend::repl();
|
repl();
|
||||||
} else if let Some(file_path) = cli.file {
|
} else if let Some(file_path) = cli.file {
|
||||||
let source_code = std::fs::read_to_string(file_path)?;
|
let source_code = std::fs::read_to_string(file_path)?;
|
||||||
let mut parser = parser::Parser::new(source_code);
|
let mut parser = parser::Parser::new(source_code);
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
use std::process;
|
||||||
|
|
||||||
|
use crate::frontend::ast::{BinaryExpr, NodeType, Program};
|
||||||
|
use crate::runtime::values::ValueType;
|
||||||
|
|
||||||
|
fn eval_program(program: Program) -> ValueType {
|
||||||
|
// Initialize with your equivalent of NullVal
|
||||||
|
let mut last_evaluated = ValueType::Null;
|
||||||
|
|
||||||
|
// Iterate through each statement in the program body
|
||||||
|
for statement in program.body {
|
||||||
|
last_evaluated = evaluate(statement);
|
||||||
|
}
|
||||||
|
|
||||||
|
last_evaluated
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eval_binop(binop: BinaryExpr) -> ValueType {
|
||||||
|
let lhs = evaluate(*binop.left);
|
||||||
|
let rhs = evaluate(*binop.right);
|
||||||
|
|
||||||
|
match (&lhs, &rhs) {
|
||||||
|
(ValueType::Number(l), ValueType::Number(r)) => eval_num_binop(*l, *r, binop.operator),
|
||||||
|
_ => ValueType::Null,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eval_num_binop(lhs: f64, rhs: f64, operator: String) -> ValueType {
|
||||||
|
let result: f64;
|
||||||
|
|
||||||
|
match operator.as_str() {
|
||||||
|
"+" => result = lhs + rhs,
|
||||||
|
"-" => result = lhs - rhs,
|
||||||
|
"*" => result = lhs * rhs,
|
||||||
|
// TODO: Handle division by zero
|
||||||
|
"/" => result = lhs / rhs,
|
||||||
|
"%" => result = lhs % rhs,
|
||||||
|
_ => {
|
||||||
|
eprintln!("Unknown operator: {}", operator);
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueType::Number(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn evaluate(node: NodeType) -> ValueType {
|
||||||
|
match node {
|
||||||
|
NodeType::NumericLiteral(n) => ValueType::Number(n.value),
|
||||||
|
NodeType::NullLiteral(_) => ValueType::Null,
|
||||||
|
NodeType::BinaryExpr(e) => eval_binop(e),
|
||||||
|
NodeType::Program(p) => eval_program(p),
|
||||||
|
_ => {
|
||||||
|
eprintln!(
|
||||||
|
"Evaluation for node type {:#?} is not implemented yet.",
|
||||||
|
node
|
||||||
|
);
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
pub mod interpreter;
|
||||||
|
pub mod values;
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum ValueType {
|
||||||
|
Null,
|
||||||
|
Number(f64),
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user