Skip to content

Commit

Permalink
add native functions functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
nulluser committed Jun 1, 2024
1 parent 72a473a commit dbffc36
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 5 deletions.
10 changes: 8 additions & 2 deletions src/backend/environment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
use std::collections::{HashMap, HashSet};
use std::process;

use crate::backend::values::{BoolVal, NullVal, Val};
use crate::{mk_bool, mk_null};
use crate::backend::values::{BoolVal, NativeFunctionVal, NullVal, Val};
use crate::{mk_bool, mk_native_fn, mk_null};

use super::native_fn::{native_println, native_time};

#[derive(Debug, Clone)]
pub struct Environment<'a> {
Expand All @@ -20,9 +22,13 @@ impl<'a> Default for Environment<'a> {
}

fn setup_env(env: &mut Environment) {
// Create Default Global Environment
env.declare_var("null", mk_null!(), false);
env.declare_var("true", mk_bool!(true), false);
env.declare_var("false", mk_bool!(false), false);
// Define a native built-in method
env.declare_var("println", mk_native_fn!(native_println), false);
env.declare_var("time", mk_native_fn!(native_time), false);
}

impl<'a> Environment<'a> {
Expand Down
15 changes: 14 additions & 1 deletion src/backend/eval/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub fn evaluate_expr(expr: Expr, env: &mut Environment) -> Val {
Expr::Identifier(identifier) => evaluate_identifier(identifier, env),
Expr::BinaryOp { op, left, right } => evaluate_binary_op(op, *left, *right, env),
Expr::UnaryOp(_, _) => unimplemented!("{:?}", expr),
Expr::FunctionCall(_, _) => unimplemented!("{:?}", expr),
Expr::FunctionCall(args, caller) => evaluate_call_expr(args, *caller, env),
Expr::AssignmentExpr(assignee, expr) => evaluate_assignment(*assignee, *expr, env),
Expr::Member(_, _, _) => todo!("{:?}", expr),
}
Expand Down Expand Up @@ -55,6 +55,19 @@ pub fn evaluate_object_expr(obj: Vec<Property>, env: &mut Environment) -> Val {
Val::Object(object)
}

pub fn evaluate_call_expr(args: Vec<Expr>, caller: Expr, env: &mut Environment) -> Val {
let evaluated_args: Vec<Val> = args
.into_iter()
.map(|expr| evaluate_expr(expr, env))
.collect();
let function = evaluate_expr(caller, env);
let callable = match function {
Val::NativeFunction(callable) => callable.call,
_ => panic!("Cannot call value that is not a function: {:?}", function),
};
callable(evaluated_args, env)
}

pub fn evaluate_binary_op(op: BinaryOp, left: Expr, right: Expr, env: &mut Environment) -> Val {
let left_val = evaluate_expr(left, env);
let right_val = evaluate_expr(right, env);
Expand Down
1 change: 1 addition & 0 deletions src/backend/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod environment;
pub mod eval;
pub mod interpreter;
pub mod native_fn;
pub mod values;
22 changes: 22 additions & 0 deletions src/backend/native_fn.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use std::time::SystemTime;

use crate::{mk_integer, mk_null};

use super::{environment::Environment, values::Val};
use crate::backend::values::{IntegerVal, NullVal};

pub fn native_println(args: Vec<Val>, _env: &mut Environment) -> Val {
for arg in args {
println!("{:?}", arg); // for now, just use debug print.
// TODO: Add actual std::fmt::Display impl for Val enums.
}
mk_null!()
}

pub fn native_time(_args: Vec<Val>, _env: &mut Environment) -> Val {
let time = match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {
Ok(n) => n.as_secs() as i64,
Err(e) => panic!("SystemTime before UNIX EPOCH! {}", e),
};
mk_integer!(time)
}
25 changes: 25 additions & 0 deletions src/backend/values.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
use std::collections::HashMap;

use super::environment::Environment;

#[derive(Debug, PartialEq)]
pub enum ValueType {
Null,
Float,
Integer,
Bool,
Object,
NativeFunction,
}

pub trait RuntimeVal: std::fmt::Debug {
Expand Down Expand Up @@ -76,6 +79,19 @@ impl RuntimeVal for ObjectVal {
}
}

type NativeFunctionCallback = fn(Vec<Val>, &mut Environment) -> Val;

#[derive(Debug, PartialEq, Clone)]
pub struct NativeFunctionVal {
pub call: NativeFunctionCallback,
}

impl RuntimeVal for NativeFunctionVal {
fn get_type(&self) -> ValueType {
ValueType::NativeFunction
}
}

// This enum encapsulates any RuntimeVal type to handle them generically.
#[derive(Debug, PartialEq, Clone)]
pub enum Val {
Expand All @@ -84,6 +100,7 @@ pub enum Val {
Integer(IntegerVal),
Bool(BoolVal),
Object(ObjectVal),
NativeFunction(NativeFunctionVal),
}

impl RuntimeVal for Val {
Expand All @@ -94,6 +111,7 @@ impl RuntimeVal for Val {
Val::Integer(_) => ValueType::Integer,
Val::Bool(_) => ValueType::Bool,
Val::Object(_) => ValueType::Object,
Val::NativeFunction(_) => ValueType::NativeFunction,
}
}
}
Expand Down Expand Up @@ -135,3 +153,10 @@ macro_rules! mk_integer {
mk_integer!(0)
};
}

#[macro_export]
macro_rules! mk_native_fn {
($n:expr) => {
Val::NativeFunction(NativeFunctionVal { call: $n })
};
}
3 changes: 1 addition & 2 deletions src/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ fn repl() {
// println!("{:#?}", program);

for stmt in program.statements {
let result = evaluate(stmt, &mut env);
println!("{:?}", result);
let _ = evaluate(stmt, &mut env);
}
}
Err(e) => {
Expand Down

0 comments on commit dbffc36

Please sign in to comment.