mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
DEV: Simple scalar expressions compile.
This commit is contained in:
parent
9f31a16b93
commit
27ac204c48
@ -19,6 +19,7 @@ mod error;
|
||||
pub mod pointer;
|
||||
mod runtime;
|
||||
pub mod scope;
|
||||
mod translate;
|
||||
mod vm;
|
||||
|
||||
pub use error::Error;
|
||||
|
@ -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())),
|
||||
)
|
||||
}
|
79
src/build/opcode/translate.rs
Normal file
79
src/build/opcode/translate.rs
Normal 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"),
|
||||
}
|
||||
}
|
||||
}
|
@ -31,6 +31,7 @@ pub struct VM {
|
||||
symbols: Stack,
|
||||
runtime: Rc<RefCell<runtime::Builtins>>,
|
||||
ops: OpPointer,
|
||||
// TODO(jwall): This should be optional
|
||||
path: PathBuf,
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user