Skip to content

Commit

Permalink
Remove eval, update native function macro for bytecode
Browse files Browse the repository at this point in the history
Quaqqer committed Jan 23, 2024
1 parent d2de176 commit 2abf807
Showing 14 changed files with 115 additions and 1,438 deletions.
12 changes: 1 addition & 11 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -2,9 +2,11 @@
resolver = "2"
members = [
"crates/saft",
"crates/saft-ast", "crates/saft-ast-to-ir", "crates/saft-bytecode",
"crates/saft-ast",
"crates/saft-ast-to-ir",
"crates/saft-bytecode",
"crates/saft-common",
"crates/saft-eval", "crates/saft-ir",
"crates/saft-ir",
"crates/saft-lexer",
"crates/saft-macro",
"crates/saft-parser",
1 change: 1 addition & 0 deletions crates/saft-bytecode/Cargo.toml
Original file line number Diff line number Diff line change
@@ -9,3 +9,4 @@ edition = "2021"
codespan-reporting = "0.11.1"
saft-common = { version = "0.1.0", path = "../saft-common" }
saft-ir = { version = "0.1.0", path = "../saft-ir" }
saft-macro = { version = "0.1.0", path = "../saft-macro" }
13 changes: 9 additions & 4 deletions crates/saft-bytecode/src/compiler.rs
Original file line number Diff line number Diff line change
@@ -4,7 +4,12 @@ use codespan_reporting::diagnostic::{Diagnostic, Label};
use saft_common::span::{Span, Spanned};
use saft_ir as ir;

use crate::{chunk::Chunk, constant::Constant, op::Op, value::SaftFunction};
use crate::{
chunk::Chunk,
constant::Constant,
op::Op,
value::{Function, SaftFunction},
};

pub enum Error {
Exotic {
@@ -89,9 +94,9 @@ impl Compiler {
let item = item.as_ref().expect("Should not be none");

let constant = match &item.v {
ir::Item::Function(fun) => {
Constant::SaftFunction(self.compile_fn(item.s.spanned(fun))?)
}
ir::Item::Function(fun) => Constant::Function(Function::SaftFunction(
self.compile_fn(item.s.spanned(fun))?,
)),
ir::Item::Builtin(_) => todo!(),
};

9 changes: 2 additions & 7 deletions crates/saft-bytecode/src/constant.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
use crate::{value::SaftFunction, vm};
use crate::value::Function;

#[derive(Clone, Debug)]
pub enum Constant {
SaftFunction(SaftFunction),
}

#[derive(Clone)]
pub struct NativeFunction {
_f: fn(&mut vm::Vm) -> Result<(), vm::Error>,
Function(Function),
}
36 changes: 35 additions & 1 deletion crates/saft-bytecode/src/value.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use std::fmt::Write;
use std::rc::Rc;

use crate::{chunk::Chunk, num::Num};
use saft_common::span::Span;
use saft_macro::native_function;

use crate::{chunk::Chunk, num::Num, vm};

#[derive(Debug, Clone)]
pub enum Value {
@@ -14,6 +17,7 @@ pub enum Value {
#[derive(Debug, Clone)]
pub enum Function {
SaftFunction(SaftFunction),
NativeFunction(NativeFunction),
}

#[derive(Debug, Clone)]
@@ -22,6 +26,36 @@ pub struct SaftFunction {
pub chunk: Rc<Chunk>,
}

#[derive(Debug, Clone)]
pub struct NativeFunction {
f: fn(&mut vm::Vm, Vec<Value>, Span) -> Result<Value, vm::Error>,
}

struct NativeRes(Result<Value, vm::Error>);

impl From<Value> for NativeRes {
fn from(value: Value) -> Self {
NativeRes(Ok(value))
}
}

impl From<Result<Value, vm::Error>> for NativeRes {
fn from(value: Result<Value, vm::Error>) -> Self {
NativeRes(value)
}
}

impl From<()> for NativeRes {
fn from(_value: ()) -> Self {
NativeRes(Ok(Value::Nil))
}
}

#[native_function]
fn test(_: i64) -> Value {
todo!()
}

impl Value {
pub fn or(&self, rhs: &Value) -> Option<bool> {
match (self, rhs) {
21 changes: 17 additions & 4 deletions crates/saft-bytecode/src/vm.rs
Original file line number Diff line number Diff line change
@@ -205,6 +205,18 @@ impl Vm {

match fun {
Value::Function(Function::SaftFunction(fun)) => {
if fun.arity != args.len() {
exotic!(
"Wrong parameters",
s,
format!(
"Function expected {} arguments but got {}",
fun.arity,
args.len()
)
);
}

self.call_stack.last_mut().unwrap().i += 1;
self.enter_frame(fun.chunk.clone());
for arg in args {
@@ -274,11 +286,12 @@ impl Vm {
};
}
Op::Constant(ref_) => match &constants[*ref_] {
Constant::SaftFunction(saft_function) => {
Constant::Function(Function::SaftFunction(saft_function)) => {
self.push(Value::Function(Function::SaftFunction(
saft_function.clone(),
)));
}
Constant::Function(Function::NativeFunction(_)) => todo!(),
},
}

@@ -287,15 +300,15 @@ impl Vm {
Ok(())
}

fn push(&mut self, v: Value) {
pub(crate) fn push(&mut self, v: Value) {
self.stack.push(v);
}

fn pop(&mut self) -> Value {
pub(crate) fn pop(&mut self) -> Value {
self.stack.pop().unwrap()
}

fn popn(&mut self, n: usize) -> Vec<Value> {
pub(crate) fn popn(&mut self, n: usize) -> Vec<Value> {
self.stack.split_off(self.stack.len() - n)
}

13 changes: 0 additions & 13 deletions crates/saft-eval/Cargo.toml

This file was deleted.

801 changes: 0 additions & 801 deletions crates/saft-eval/src/interpreter.rs

This file was deleted.

4 changes: 0 additions & 4 deletions crates/saft-eval/src/lib.rs

This file was deleted.

76 changes: 0 additions & 76 deletions crates/saft-eval/src/natives.rs

This file was deleted.

469 changes: 0 additions & 469 deletions crates/saft-eval/src/value.rs

This file was deleted.

90 changes: 45 additions & 45 deletions crates/saft-macro/src/native_function.rs
Original file line number Diff line number Diff line change
@@ -4,20 +4,20 @@ use syn::{PatIdent, TypeReference};
enum Parameter {
Normal(syn::Type),
Span { by_ref: bool },
Interpreter,
Vm,
}

fn parse_param(arg: &syn::FnArg) -> Parameter {
match arg {
syn::FnArg::Typed(syn::PatType {
box ty, box pat, ..
}) => match pat {
syn::Pat::Ident(PatIdent { ident, .. }) if ident == "interpreter" => {
syn::Pat::Ident(PatIdent { ident, .. }) if ident == "vm" => {
match ty {
syn::Type::Reference(TypeReference { .. }) => {}
_ => panic!("Must take interpreter by reference"),
_ => panic!("Must take vm by reference"),
}
Parameter::Interpreter
Parameter::Vm
}
syn::Pat::Ident(PatIdent { ident, .. }) if ident == "span" => match ty {
syn::Type::Reference(TypeReference { .. }) => Parameter::Span { by_ref: true },
@@ -29,13 +29,10 @@ fn parse_param(arg: &syn::FnArg) -> Parameter {
}
}

pub fn expand_native_function(mut fn_: syn::ItemFn) -> syn::Result<proc_macro2::TokenStream> {
pub fn expand_native_function(fn_: syn::ItemFn) -> syn::Result<proc_macro2::TokenStream> {
let name = fn_.sig.ident.clone();
let name_s = name.to_string();
let inner = format_ident!("inner");
fn_.sig.ident = inner.clone();

let params: Vec<_> = fn_.sig.inputs.iter().map(parse_param).collect();
let params = fn_.sig.inputs.iter().map(parse_param).collect::<Vec<_>>();

let mut inner_args = Vec::<(syn::Ident, proc_macro2::TokenStream)>::new();

@@ -49,12 +46,12 @@ pub fn expand_native_function(mut fn_: syn::ItemFn) -> syn::Result<proc_macro2::
arg_i += 1;
ts
}
Parameter::Interpreter => {
quote!(interpreter)
Parameter::Vm => {
quote!(vm)
}
Parameter::Span { by_ref } => {
if *by_ref {
quote!(span)
quote!(&span)
} else {
quote!(span.clone())
}
@@ -63,52 +60,55 @@ pub fn expand_native_function(mut fn_: syn::ItemFn) -> syn::Result<proc_macro2::

inner_args.push((ident, expr));
}

let normal_params = arg_i;

let (arg_ident, arg_expr): (Vec<_>, Vec<_>) = inner_args.iter().cloned().unzip();
let (rev_arg_ident, rev_arg_expr): (Vec<_>, Vec<_>) = inner_args.iter().rev().cloned().unzip();
let arg_ident = rev_arg_ident.iter().rev().collect::<Vec<_>>();

Ok(quote! {
#[allow(non_camel_case_types)]
#[derive(Debug)]
struct #name {}

impl NativeFunc for #name {
fn data() -> NativeFuncData {
fn #name(interpreter: &mut Interpreter, span: &Span, args: Vec<Spanned<Value>>) -> Result<Value, ControlFlow> {
#fn_

if args.len() != #normal_params {
return Err(Exception::ArgMismatch {
span: span.clone(),
expected: #normal_params,
got: args.len(),
}.into())
}

#(let #arg_ident = #arg_expr;)*

let res: NativeRes = #inner(#(#arg_ident),*).into();
res.0
#[allow(non_upper_case_globals)]
const #name: NativeFunction = {
fn inner(vm: &mut vm::Vm, mut args: Vec<Value>, span: Span) -> Result<Value, vm::Error> {
#fn_

if args.len() != #normal_params {
return Err(vm::Error::Exotic {
message: "Wrong parameters".into(),
span,
note: Some(format!(
"Function expected {} arguments but got {}",
#normal_params,
args.len()
)),
});
}

NativeFuncData {
name: #name_s,
f: #name,
}
#(let #rev_arg_ident = #rev_arg_expr;)*

NativeRes::from(#name(#(#arg_ident),*)).0
}
}

NativeFunction { f: inner }
};
})
}

fn parse_normal(i: usize, ty: &syn::Type) -> proc_macro2::TokenStream {
quote! {
{
let arg = &args[#i];
Cast::<#ty>::cast(arg.v.clone()).ok_or::<ControlFlow>(
cast_error!(arg.clone(),
<#ty as CastFrom::<Value>>::ty_name()
)
)?
let arg = args.pop().unwrap();
let casted: #ty = arg.cast().ok_or_else(|| vm::Error::Exotic {
message: "Cast error".into(),
span: span.clone(),
note: Some(format!(
"Could not cast argument {} of type {} to {}",
#i,
arg.ty().name(),
<Value as Cast<#ty>>::name(),
)),
})?;
casted
}
}
}
2 changes: 1 addition & 1 deletion crates/saft/src/main.rs
Original file line number Diff line number Diff line change
@@ -24,7 +24,7 @@ struct Args {
}

pub struct Saft {
lowerer: saft_ast_to_ir::Lowerer<bytecode::constant::NativeFunction>,
lowerer: saft_ast_to_ir::Lowerer<bytecode::value::NativeFunction>,
compiler: bytecode::compiler::Compiler,
vm: Vm,
diagnostic_writer: StandardStream,

0 comments on commit 2abf807

Please sign in to comment.