Commit 37e313b5 authored by Daan Sprenkels's avatar Daan Sprenkels
Browse files

Merge branch 'master' of gitlab.science.ru.nl:dsprenkels/rsplt

parents 7438a232 f8f7a4d0
Pipeline #3593 failed with stage
facI (n) :: Int -> Int {
var r = 1;
while (n > 1) {
r = r * n;
n = n - 1;
}
return r;
}
main () :: Int {
print(facI( 6 ));
return 0;
}
......@@ -7,6 +7,6 @@ facR (n) :: Int -> Int {
}
main() :: Int {
print(facR(7));
print(facR(6));
return 0;
}
This diff is collapsed.
use std::fmt;
//use ast;
pub trait ToSSMCode {
fn to_ssm_code(&self) -> Vec<SSMLine>;
}
/* EBNF grammar for SSM, from https://www.staff.science.uu.nl/~dijks106/SSM/instructions.html
AssemblySource ::= Line *
Line ::= ((Label ":") ?) (Instruction ?) (Comment ?) EOL
Label ::= Identifier
Instruction ::= ("ldc" | ...) (Argument *)
Argument ::= Label | ("-" ?) Number
Number ::= Decimal | HexaDecimal
Decimal ::= (DecDigit *)
HexaDecimal ::= "0x" (HexDigit *)
DecDigit ::= "0" .. "9"
HexDigit ::= DecDigit | "a" .. "z" | "A" .. "Z"
Comment ::= (";" | "//") ..
*/
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct SSM {
pub instructions: Vec<SSMLine>
}
/* we print each SSMLine in main.rs
impl fmt::Display for SSM {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut indent = false;
for (count, v) in self.instructions.iter().enumerate() {
match v {
&SSMLine::SSMLabel(ref x) => indent = !indent,
_ => {}
}
if indent { try!(write!(f, "\t")); }
try!(write!(f, "{}", v))
}
Ok(())
}
}
*/
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum SSMLine {
SSMLabel(String),
Instruction(Operation),
Comment(String),
Literal(SSMLiteral)
}
impl fmt::Display for SSMLine {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&SSMLine::SSMLabel(ref x) => write!(f, "{}:" , x),
&SSMLine::Instruction(ref x) => write!(f, "{}" , x),
&SSMLine::Comment(ref x) => write!(f, "; {}", x),
&SSMLine::Literal(ref x) => write!(f, "{}", x),
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum SSMLiteral {
LiteralString(String),
LiteralNumber(i64)
}
impl fmt::Display for SSMLiteral {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
SSMLiteral::LiteralString(ref x) => write!(f, "{}" , x),
SSMLiteral::LiteralNumber(ref x) => write!(f, "{}" , x),
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Operation {
Load(LoadType),
Store(StoreType),
Compute(ComputeType),
Control(ControlType)
}
impl fmt::Display for Operation {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&Operation::Load(ref x) => write!(f, "{}", x),
&Operation::Store(ref x) => write!(f, "{}", x),
&Operation::Compute(ref x) => write!(f, "{}", x),
&Operation::Control(ref x) => write!(f, "{}", x),
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum LoadType {
Constant(OpArg),
Stack(OpArg),
Heap(OpArg),
Mark(OpArg),
Address(OpArg),
Register(OpArg),
RegFromReg(OpArg, OpArg),
StackAddress(OpArg),
MarkAddress(OpArg),
AddressAddress(OpArg) /* Load Address of Address. Pushes the address of a value relative
* to the address on top of the stack. This instruction effectively
* adds a constant to the top of the stack. */
}
impl fmt::Display for LoadType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&LoadType::Constant(ref x) => write!(f, "LDC {}", x),
&LoadType::Stack(ref x) => write!(f, "LDS {}", x),
&LoadType::Heap(ref x) => write!(f, "LDH {}", x),
&LoadType::Mark(ref x) => write!(f, "LDL {}", x),
&LoadType::Address(ref x) => write!(f, "LDA {}", x),
&LoadType::Register(ref x) => write!(f, "LDR {}", x),
&LoadType::RegFromReg(ref x, ref y) => write!(f, "LDRR {} {}", x, y),
&LoadType::StackAddress(ref x) => write!(f, "LDSA {}", x),
&LoadType::MarkAddress(ref x) => write!(f, "LDLA {}", x),
&LoadType::AddressAddress(ref x) => write!(f, "LDAA {}", x),
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum StoreType {
Stack(OpArg),
Heap, /* no argument */
Mark(OpArg),
Address(OpArg),
Register(OpArg),
HeapMultiple(OpArg)
}
impl fmt::Display for StoreType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&StoreType::Stack(ref x) => write!(f, "STS {}", x),
&StoreType::Heap => write!(f, "STH" ),
&StoreType::Mark(ref x) => write!(f, "STL {}", x),
&StoreType::Address(ref x) => write!(f, "STA {}", x),
&StoreType::Register(ref x) => write!(f, "STR {}", x),
&StoreType::HeapMultiple(ref x) => write!(f, "STMH {}", x),
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ComputeType {
Add, Sub, Mul, Div, Mod, Neg,
And, Or, Xor, Not,
Cmp,
Eq, Ne, Lt, Gt, Le, Ge,
Cons
}
impl fmt::Display for ComputeType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&ComputeType::Add => write!(f, "ADD"),
&ComputeType::Sub => write!(f, "SUB"),
&ComputeType::Mul => write!(f, "MUL"),
&ComputeType::Div => write!(f, "DIV"),
&ComputeType::Mod => write!(f, "MOD"),
&ComputeType::Neg => write!(f, "NEG"),
&ComputeType::And => write!(f, "AND"),
&ComputeType::Or => write!(f, "OR"),
&ComputeType::Xor => write!(f, "XOR"),
&ComputeType::Not => write!(f, "NOT"),
&ComputeType::Cmp => write!(f, "CMP"),
&ComputeType::Eq => write!(f, "EQ"),
&ComputeType::Ne => write!(f, "NE"),
&ComputeType::Lt => write!(f, "LT"),
&ComputeType::Gt => write!(f, "GT"),
&ComputeType::Le => write!(f, "LE"),
&ComputeType::Ge => write!(f, "GE"),
&ComputeType::Cons=> write!(f, "TODO: cons"),
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ControlType {
Beq(OpArg), Bne(OpArg), /* equality */
Blt(OpArg), Bgt(OpArg), Ble(OpArg), Bge(OpArg), /* comparison */
Brf(OpArg), Brt(OpArg), /* false(0) true(1) */
Bra(OpArg), Bsr(OpArg), /* always, subroutine */
Ret, /* return from subroutine */
Jsr, /* jump to subroutine, pop destination from stack */
Halt,
Link(OpArg), Unlink,
Ajs(OpArg), Trap(OpArg)
}
impl fmt::Display for ControlType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&ControlType::Beq(ref x) => write!(f, "BEQ {}", x),
&ControlType::Bne(ref x) => write!(f, "BNE {}", x),
&ControlType::Blt(ref x) => write!(f, "BLT {}", x),
&ControlType::Bgt(ref x) => write!(f, "BGT {}", x),
&ControlType::Ble(ref x) => write!(f, "BLE {}", x),
&ControlType::Bge(ref x) => write!(f, "BGE {}", x),
&ControlType::Brf(ref x) => write!(f, "BRF {}", x),
&ControlType::Brt(ref x) => write!(f, "BRT {}", x),
&ControlType::Bra(ref x) => write!(f, "BRA {}", x),
&ControlType::Bsr(ref x) => write!(f, "BSR {}", x),
&ControlType::Jsr => write!(f, "JSR" ),
&ControlType::Ret => write!(f, "RET" ),
&ControlType::Halt => write!(f, "HALT" ),
&ControlType::Link(ref x)=> write!(f, "LINK {}", x),
&ControlType::Unlink => write!(f, "UNLINK" ),
&ControlType::Ajs(ref x) => write!(f, "AJS {}", x),
&ControlType::Trap(ref x)=> write!(f, "TRAP {}", x),
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum OpArg {
SSMLabel(String),
SSMNumber(Number),
LiteralString(String),
LiteralInt(i64)
}
impl fmt::Display for OpArg {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&OpArg::SSMLabel(ref x) => write!(f, "{}:", x),
&OpArg::SSMNumber(ref x) => write!(f, "{}", x),
&OpArg::LiteralString(ref x) => write!(f, "{}", x),
&OpArg::LiteralInt(ref x) => write!(f, "{}", x),
}
}
}
/* TODO: maybe delete Number and NumberType, since we can output literal strings and integers */
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Number {
PositiveNumber(NumberType),
NegativeNumber(NumberType),
}
impl fmt::Display for Number {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&Number::PositiveNumber(ref x) => write!(f, "{}", x),
&Number::NegativeNumber(ref x) => write!(f, "-{}", x),
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum NumberType {
Decimal(i64),
Hexadecimal(i64)
}
impl fmt::Display for NumberType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&NumberType::Decimal(ref x) => write!(f, "{}", x),
&NumberType::Hexadecimal(ref x) => write!(f, "{}", x), // TODO
}
}
}
......@@ -507,6 +507,11 @@ impl ast::FunCall {
act_arg.unify_free_variables(spl, fun_decl);
}
if self.fun_name.clone().name == "print" ||
self.fun_name.clone().name == "putChar" ||
self.fun_name.clone().name == "isEmpty" {
return;
}
let ref mut ident = self.fun_name;
if let Some(other) = search_environments_fun(spl, fun_decl, &ident.clone()) {
let other_type = other.spl_type.clone();
......@@ -523,6 +528,12 @@ impl ast::FunCall {
if act_arg.try_inference() {return true}
}
if self.fun_name.clone().name == "print" ||
self.fun_name.clone().name == "putChar" ||
self.fun_name.clone().name == "isEmpty" {
return false;
}
let fun_type = self.fun_name.spl_type.borrow();
if let Type::Function(fun_args, ret) = fun_type.clone() {
// unify acting arguments
......
......@@ -13,6 +13,7 @@ mod parser_tests;
mod scanner_tests;
mod infer;
mod infer_tests;
mod codegen;
mod llvm;
use std::fs;
......@@ -21,6 +22,8 @@ use std::io::Read;
use std::process;
use std::io::Write;
use codegen::*;
use ansi_term::Colour;
use docopt::Docopt;
......@@ -34,6 +37,7 @@ Options:
--exec JIT compile and execute the input file
--pretty-print Pretty print the output, instead of compiling
--emit-llvm Compile the input file to LLVM IR (version 3.6)
--emit-ssm Compile the input file to SSM
-h --help Display this message
--version Print version info and exit
-v --verbose Use verbose output
......@@ -47,6 +51,7 @@ struct Args {
flag_help: bool,
flag_exec: bool,
flag_emit_llvm: bool,
flag_emit_ssm: bool,
flag_pretty_print: bool,
flag_verbose: bool,
flag_version: bool,
......@@ -107,18 +112,12 @@ fn main() {
pretty_print_and_exit(ast);
}
ast.unify_free_variables();
// time for type analysis
ast.try_inference();
println!("ast:\n{}\n", ast);
println!("ast (debug):\n{:?}\n", ast);
let llvm = llvm::Context::from(ast);
print!("llvm:\n{}", llvm);
if args.flag_emit_ssm {
ast.unify_free_variables();
let ssm = ast.to_ssm_code();
emit_ssm_and_exit(ssm);
}
println!("{}\n", Colour::Green.paint("parsing succeeded :)"));
}
fn show_version_and_exit() -> ! {
......@@ -149,6 +148,17 @@ fn emit_llvm_and_exit(llvm: llvm::Context) -> ! {
process::exit(0);
}
fn emit_ssm_and_exit(ssm: Vec<SSMLine>) -> ! {
for (count, v) in ssm.iter().enumerate() {
match *v {
SSMLine::SSMLabel(ref x) => {},
_ => { print!("\t"); },
}
println!("{}", v);
}
process::exit(0);
}
fn pretty_print_and_exit(ast: ast::SPL) -> ! {
print!("{}", ast);
process::exit(0);
......
......@@ -152,7 +152,7 @@ impl Parser {
pub fn parse_spl(&mut self) -> TopParseResult<SPL> {
let offset = 0;
let mut decls = make_builtin_functions();
let mut decls = Vec::new(); //make_builtin_functions();
let (new_decl, mut offset) = try_parse!(self.parse_decl(offset));
decls.push(new_decl);
loop {
......
BRA main
facR:
LINK 0
LDL -2 // facR( n )
LDC 2
LT
BRF recurse // if (n < 2)
LDC 1
unlink
RET // return 1
recurse: // else
LDL -2 // n
LDL -2 // n
LDC 1 // 1
SUB // n - 1
BSR facR // facR ( n -1 )
MUL // n * facR (n - 1)
trap 0
unlink
ret
main:
LDC 5
BSR facR
halt
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment