From a2b1b0f953db61ad3ec6cfd6f35bd7c80a09fbe3 Mon Sep 17 00:00:00 2001 From: greg Date: Tue, 24 Jul 2018 03:12:00 -0700 Subject: [PATCH] Pattern-matching in reduced AST --- README.md | 2 +- schala-lang/src/reduced_ast.rs | 58 +++++++++++++++++++--------------- 2 files changed, 33 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 003f930..f726c3d 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Schala is a Rust framework written to make it easy to create and experiment with toy programming languages. It provides -a common REPL, and a trait `ProgrammingLanguage` with provisions +a common REPL, and a trait `ProgrammingLanguage` with provisions for tokenizing text, parsing tokens, evaluating an abstract syntax tree, and other tasks that are common to all programming languages. diff --git a/schala-lang/src/reduced_ast.rs b/schala-lang/src/reduced_ast.rs index ab4af66..52c096d 100644 --- a/schala-lang/src/reduced_ast.rs +++ b/schala-lang/src/reduced_ast.rs @@ -1,6 +1,6 @@ use std::rc::Rc; -use ast::{AST, Statement, Expression, Declaration, Discriminator, IfExpressionBody}; +use ast::{AST, Statement, Expression, Declaration, Discriminator, IfExpressionBody, Pattern}; use symbol_table::{Symbol, SymbolSpec, SymbolTable}; use builtin::{BinOp, PrefixOp}; @@ -45,6 +45,10 @@ pub enum Expr { then_clause: Vec, else_clause: Vec, }, + Match { + cond: Box, + arms: Vec<(Pattern, Vec)> + }, UnimplementedSigilValue } @@ -112,36 +116,38 @@ impl Expression { args: arguments.iter().map(|arg| arg.reduce(symbol_table)).collect(), }, TupleLiteral(exprs) => Expr::Tuple(exprs.iter().map(|e| e.reduce(symbol_table)).collect()), - IfExpression { discriminator, body } => { - let cond = Box::new(match **discriminator { - Discriminator::Simple(ref expr) => expr.reduce(symbol_table), - _ => panic!(), - }); - match **body { - IfExpressionBody::SimpleConditional(ref then_clause, ref else_clause) => { - let then_clause = then_clause.iter().map(|expr| expr.reduce(symbol_table)).collect(); - let else_clause = match else_clause { - None => vec![], - Some(stmts) => stmts.iter().map(|expr| expr.reduce(symbol_table)).collect(), - }; - Expr::Conditional { cond, then_clause, else_clause } - }, - IfExpressionBody::SimplePatternMatch(ref pat, ref then_clause, ref else_clause) => { - let then_clause = then_clause.iter().map(|expr| expr.reduce(symbol_table)).collect(); - let else_clause = match else_clause { - None => vec![], - Some(stmts) => stmts.iter().map(|expr| expr.reduce(symbol_table)).collect(), - }; - Expr::Conditional { cond, then_clause, else_clause } - }, - _ => panic!(), - } - }, + IfExpression { discriminator, body } => reduce_if_expression(discriminator, body, symbol_table), _ => Expr::UnimplementedSigilValue, } } } +fn reduce_if_expression(discriminator: &Discriminator, body: &IfExpressionBody, symbol_table: &SymbolTable) -> Expr { + let cond = Box::new(match *discriminator { + Discriminator::Simple(ref expr) => expr.reduce(symbol_table), + _ => panic!(), + }); + match *body { + IfExpressionBody::SimpleConditional(ref then_clause, ref else_clause) => { + let then_clause = then_clause.iter().map(|expr| expr.reduce(symbol_table)).collect(); + let else_clause = match else_clause { + None => vec![], + Some(stmts) => stmts.iter().map(|expr| expr.reduce(symbol_table)).collect(), + }; + Expr::Conditional { cond, then_clause, else_clause } + }, + IfExpressionBody::SimplePatternMatch(ref pat, ref then_clause, ref else_clause) => { + let then_clause = then_clause.iter().map(|expr| expr.reduce(symbol_table)).collect(); + let else_clause = match else_clause { + None => vec![], + Some(stmts) => stmts.iter().map(|expr| expr.reduce(symbol_table)).collect(), + }; + Expr::Conditional { cond, then_clause, else_clause } + }, + _ => panic!(), + } +} + impl Declaration { fn reduce(&self, symbol_table: &SymbolTable) -> Stmt { use self::Declaration::*;