DEV: Simple scalar expressions compile.

This commit is contained in:
Jeremy Wall 2019-07-29 17:51:08 -05:00
parent 9f31a16b93
commit 27ac204c48
4 changed files with 131 additions and 13 deletions

View File

@ -19,6 +19,7 @@ mod error;
pub mod pointer; pub mod pointer;
mod runtime; mod runtime;
pub mod scope; pub mod scope;
mod translate;
mod vm; mod vm;
pub use error::Error; pub use error::Error;

View File

@ -20,7 +20,7 @@ use super::Op::{
InitThunk, InitTuple, Jump, JumpIfFalse, JumpIfTrue, Module, Mul, Noop, Pop, Return, InitThunk, InitTuple, Jump, JumpIfFalse, JumpIfTrue, Module, Mul, Noop, Pop, Return,
SelectJump, Sub, Sym, Val, 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::Value::{C, P};
use super::VM; use super::VM;
@ -45,7 +45,7 @@ macro_rules! assert_cases {
} }
#[test] #[test]
fn test_math_ops() { fn math_ops() {
assert_cases!( assert_cases!(
// 1+1; // 1+1;
vec![Val(Int(1)), Val(Int(1)), Add] => P(Int(2)), vec![Val(Int(1)), Val(Int(1)), Add] => P(Int(2)),
@ -79,7 +79,7 @@ fn test_math_ops() {
} }
#[test] #[test]
fn test_bind_op() { fn bind_op() {
let mut cases = vec![( let mut cases = vec![(
vec![Sym("foo".to_owned()), Val(Int(1)), Bind], vec![Sym("foo".to_owned()), Val(Int(1)), Bind],
("foo", P(Int(1))), ("foo", P(Int(1))),
@ -97,7 +97,7 @@ fn test_bind_op() {
} }
#[test] #[test]
fn test_list_ops() { fn list_ops() {
assert_cases!( assert_cases!(
vec![InitList] => C(List(Vec::new())), vec![InitList] => C(List(Vec::new())),
vec![InitList, Val(Int(1)), Element] => C(List(vec![Rc::new(P(Int(1)))])), vec![InitList, Val(Int(1)), Element] => C(List(vec![Rc::new(P(Int(1)))])),
@ -115,7 +115,7 @@ fn test_list_ops() {
} }
#[test] #[test]
fn test_tuple_ops() { fn tuple_ops() {
assert_cases!( assert_cases!(
vec![InitTuple] => C(Tuple(Vec::new())), vec![InitTuple] => C(Tuple(Vec::new())),
vec![ vec![
@ -193,14 +193,14 @@ fn test_tuple_ops() {
} }
#[test] #[test]
fn test_jump_ops() { fn jump_ops() {
assert_cases!( assert_cases!(
vec![Jump(1), Val(Int(1)), Noop, Val(Int(1))] => P(Int(1)), vec![Jump(1), Val(Int(1)), Noop, Val(Int(1))] => P(Int(1)),
); );
} }
#[test] #[test]
fn test_equality_ops() { fn equality_ops() {
assert_cases![ assert_cases![
vec![ vec![
Val(Str("foo".to_owned())), Val(Str("foo".to_owned())),
@ -261,7 +261,7 @@ fn test_equality_ops() {
} }
#[test] #[test]
fn test_conditional_jump_ops() { fn conditional_jump_ops() {
assert_cases![ assert_cases![
vec![ vec![
Val(Bool(false)), Val(Bool(false)),
@ -311,7 +311,7 @@ fn test_conditional_jump_ops() {
} }
#[test] #[test]
fn test_function_definition_and_call() { fn function_definition_and_call() {
assert_cases![ assert_cases![
vec![ vec![
Sym("f".to_owned()), // 0 Sym("f".to_owned()), // 0
@ -348,7 +348,7 @@ fn test_function_definition_and_call() {
} }
#[test] #[test]
fn test_module_call() { fn module_call() {
assert_cases![ assert_cases![
vec![ vec![
InitTuple, // 0 // override tuple InitTuple, // 0 // override tuple
@ -411,7 +411,7 @@ fn test_module_call() {
} }
#[test] #[test]
fn test_select_short_circuit() { fn select_short_circuit() {
assert_cases![ assert_cases![
vec![ vec![
Sym("field".to_owned()), // 0 // search field Sym("field".to_owned()), // 0 // search field
@ -443,7 +443,7 @@ fn test_select_short_circuit() {
} }
#[test] #[test]
fn test_index_operation() { fn index_operation() {
assert_cases![ assert_cases![
vec![ vec![
InitTuple, InitTuple,
@ -491,7 +491,7 @@ fn test_index_operation() {
} }
#[test] #[test]
fn test_scope_stacks() { fn scope_stacks() {
let mut stack = Stack::new(); let mut stack = Stack::new();
stack.add("one".to_owned(), Rc::new(P(Int(1)))); stack.add("one".to_owned(), Rc::new(P(Int(1))));
let mut val = stack.get("one").unwrap(); let mut val = stack.get("one").unwrap();
@ -502,3 +502,40 @@ fn test_scope_stacks() {
val = stack.get("one").unwrap(); val = stack.get("one").unwrap();
assert_eq!(val.as_ref(), &P(Int(1))); 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())),
)
}

View File

@ -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<Statement>) -> Vec<Op> {
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<Op>) {
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<Op>) {
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"),
}
}
}

View File

@ -31,6 +31,7 @@ pub struct VM {
symbols: Stack, symbols: Stack,
runtime: Rc<RefCell<runtime::Builtins>>, runtime: Rc<RefCell<runtime::Builtins>>,
ops: OpPointer, ops: OpPointer,
// TODO(jwall): This should be optional
path: PathBuf, path: PathBuf,
} }