From 27ac204c489f94ac4a8c05c4eb44d414e6c22e65 Mon Sep 17 00:00:00 2001 From: Jeremy Wall Date: Mon, 29 Jul 2019 17:51:08 -0500 Subject: [PATCH] DEV: Simple scalar expressions compile. --- src/build/opcode/mod.rs | 1 + src/build/opcode/test.rs | 63 ++++++++++++++++++++++------ src/build/opcode/translate.rs | 79 +++++++++++++++++++++++++++++++++++ src/build/opcode/vm.rs | 1 + 4 files changed, 131 insertions(+), 13 deletions(-) create mode 100644 src/build/opcode/translate.rs diff --git a/src/build/opcode/mod.rs b/src/build/opcode/mod.rs index 98d060c..0d76bd0 100644 --- a/src/build/opcode/mod.rs +++ b/src/build/opcode/mod.rs @@ -19,6 +19,7 @@ mod error; pub mod pointer; mod runtime; pub mod scope; +mod translate; mod vm; pub use error::Error; diff --git a/src/build/opcode/test.rs b/src/build/opcode/test.rs index 653aa44..86a21a3 100644 --- a/src/build/opcode/test.rs +++ b/src/build/opcode/test.rs @@ -20,7 +20,7 @@ use super::Op::{ InitThunk, InitTuple, Jump, JumpIfFalse, JumpIfTrue, Module, Mul, Noop, Pop, Return, SelectJump, Sub, Sym, Val, }; -use super::Primitive::{Bool, Float, Int, Str}; +use super::Primitive::{Bool, Float, Int, Str, Empty}; use super::Value::{C, P}; use super::VM; @@ -45,7 +45,7 @@ macro_rules! assert_cases { } #[test] -fn test_math_ops() { +fn math_ops() { assert_cases!( // 1+1; vec![Val(Int(1)), Val(Int(1)), Add] => P(Int(2)), @@ -79,7 +79,7 @@ fn test_math_ops() { } #[test] -fn test_bind_op() { +fn bind_op() { let mut cases = vec![( vec![Sym("foo".to_owned()), Val(Int(1)), Bind], ("foo", P(Int(1))), @@ -97,7 +97,7 @@ fn test_bind_op() { } #[test] -fn test_list_ops() { +fn list_ops() { assert_cases!( vec![InitList] => C(List(Vec::new())), vec![InitList, Val(Int(1)), Element] => C(List(vec![Rc::new(P(Int(1)))])), @@ -115,7 +115,7 @@ fn test_list_ops() { } #[test] -fn test_tuple_ops() { +fn tuple_ops() { assert_cases!( vec![InitTuple] => C(Tuple(Vec::new())), vec![ @@ -193,14 +193,14 @@ fn test_tuple_ops() { } #[test] -fn test_jump_ops() { +fn jump_ops() { assert_cases!( vec![Jump(1), Val(Int(1)), Noop, Val(Int(1))] => P(Int(1)), ); } #[test] -fn test_equality_ops() { +fn equality_ops() { assert_cases![ vec![ Val(Str("foo".to_owned())), @@ -261,7 +261,7 @@ fn test_equality_ops() { } #[test] -fn test_conditional_jump_ops() { +fn conditional_jump_ops() { assert_cases![ vec![ Val(Bool(false)), @@ -311,7 +311,7 @@ fn test_conditional_jump_ops() { } #[test] -fn test_function_definition_and_call() { +fn function_definition_and_call() { assert_cases![ vec![ Sym("f".to_owned()), // 0 @@ -348,7 +348,7 @@ fn test_function_definition_and_call() { } #[test] -fn test_module_call() { +fn module_call() { assert_cases![ vec![ InitTuple, // 0 // override tuple @@ -411,7 +411,7 @@ fn test_module_call() { } #[test] -fn test_select_short_circuit() { +fn select_short_circuit() { assert_cases![ vec![ Sym("field".to_owned()), // 0 // search field @@ -443,7 +443,7 @@ fn test_select_short_circuit() { } #[test] -fn test_index_operation() { +fn index_operation() { assert_cases![ vec![ InitTuple, @@ -491,7 +491,7 @@ fn test_index_operation() { } #[test] -fn test_scope_stacks() { +fn scope_stacks() { let mut stack = Stack::new(); stack.add("one".to_owned(), Rc::new(P(Int(1)))); let mut val = stack.get("one").unwrap(); @@ -502,3 +502,40 @@ fn test_scope_stacks() { val = stack.get("one").unwrap(); assert_eq!(val.as_ref(), &P(Int(1))); } + +use crate::ast::{Expression, Statement, Value as ASTValue, PositionedItem, Position}; +use super::translate; +use crate::parse::parse; +use crate::iter::OffsetStrIter; + +macro_rules! assert_parse_cases { + (__impl__ $cases:expr) => { + for case in $cases.drain(0..) { + let stmts = parse(OffsetStrIter::from(case.0), None).unwrap(); + let ops = Rc::new(translate::AST::translate(stmts)); + assert!(ops.len() > 0); + let mut vm = VM::new("foo.ucg", ops.clone()); + vm.run().unwrap(); + assert_eq!(dbg!(vm.pop()).unwrap(), Rc::new(case.1)); + } + }; + + ( ($input:expr, $result:expr), $( $tok:tt )* ) => { + assert_parse_cases!(__impl__ vec![($input, $result), $($tok)*]) + }; + + ( $( $input:expr => $result:expr, )* ) => { + assert_parse_cases!($(($input, $result),)*) + } +} + +#[test] +fn simple_expr_scalar_value() { + assert_parse_cases!( + "1;" => P(Int(1)), + "1.0;" => P(Float(1.0)), + "true;" => P(Bool(true)), + "NULL;" => P(Empty), + "\"foo\";" => P(Str("foo".to_owned())), + ) +} \ No newline at end of file diff --git a/src/build/opcode/translate.rs b/src/build/opcode/translate.rs new file mode 100644 index 0000000..e0285ba --- /dev/null +++ b/src/build/opcode/translate.rs @@ -0,0 +1,79 @@ +// Copyright 2019 Jeremy Wall +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +use crate::ast::{Expression, Statement, Value}; +use crate::build::opcode::Op; +use crate::build::opcode::Primitive; +use crate::build::opcode::Value::{C, F, M, P, T}; + +pub struct AST(); + +impl AST { + pub fn translate(stmts: Vec) -> Vec { + let mut ops = Vec::new(); + for stmt in stmts { + match stmt { + Statement::Expression(expr) => Self::translate_expr(expr, &mut ops), + Statement::Assert(_, _) => { + unimplemented!("Assert statements are not implmented yet") + } + Statement::Let(_) => unimplemented!("Let statements are not implmented yet"), + Statement::Output(_, _, _) => { + unimplemented!("Out statements are not implmented yet") + } + Statement::Print(_, _, _) => { + unimplemented!("Print statements are not implmented yet") + } + } + } + return ops; + } + + fn translate_expr(expr: Expression, mut ops: &mut Vec) { + match expr { + Expression::Simple(v) => { + Self::translate_value(v, &mut ops); + } + Expression::Fail(_) => unimplemented!("Fail expressions are not implmented yet"), + Expression::Format(_) => unimplemented!("Format expressions are not implmented yet"), + Expression::Func(_) => unimplemented!("Func expressions are not implmented yet"), + Expression::FuncOp(_) => unimplemented!("FuncOp expressions are not implmented yet"), + Expression::Grouped(_, _) => { + unimplemented!("Grouped expressions are not implmented yet") + } + Expression::Import(_) => unimplemented!("Import expressions are not implmented yet"), + Expression::Include(_) => unimplemented!("Include expressions are not implmented yet"), + Expression::Module(_) => unimplemented!("Module expressions are not implmented yet"), + Expression::Not(_) => unimplemented!("Not expressions are not implmented yet"), + Expression::Range(_) => unimplemented!("Range expressions are not implmented yet"), + Expression::Select(_) => unimplemented!("Select expressions are not implmented yet"), + Expression::Binary(_) => unimplemented!("Binary expressions are not implmented yet"), + Expression::Call(_) => unimplemented!("Call expressions are not implmented yet"), + Expression::Copy(_) => unimplemented!("Copy expressions are not implmented yet"), + Expression::Debug(_) => unimplemented!("Debug expressions are not implmented yet"), + } + } + + fn translate_value(value: Value, ops: &mut Vec) { + match value { + Value::Int(i) => ops.push(Op::Val(Primitive::Int(i.val))), + Value::Float(f) => ops.push(Op::Val(Primitive::Float(f.val))), + Value::Str(s) => ops.push(Op::Val(Primitive::Str(s.val))), + Value::Empty(_pos) => ops.push(Op::Val(Primitive::Empty)), + Value::Boolean(b) => ops.push(Op::Val(Primitive::Bool(b.val))), + Value::Symbol(s) => ops.push(Op::Sym(s.val)), + Value::Tuple(_flds) => unimplemented!("Select expression are not implmented yet"), + Value::List(_els) => unimplemented!("Select expression are not implmented yet"), + } + } +} diff --git a/src/build/opcode/vm.rs b/src/build/opcode/vm.rs index 62d5290..0c228d6 100644 --- a/src/build/opcode/vm.rs +++ b/src/build/opcode/vm.rs @@ -31,6 +31,7 @@ pub struct VM { symbols: Stack, runtime: Rc>, ops: OpPointer, + // TODO(jwall): This should be optional path: PathBuf, }