Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions rc.byte
1 change: 1 addition & 0 deletions rc.native
9 changes: 7 additions & 2 deletions regression/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
TESTS=test001 test002 test012 test013 test003 test004 test005 test006 test007 test008 test009 test010 test011 test014 test015 test016 test017 test018
TESTS=test002 test012 test013 test001

# test019 test020 test021 test022 test023 test024 test025 test026
# More expressions:
# test003 test004 test005 test006 test007 test008

# Later:
# test009 test010 test 11
# test014 test015 test016 test017 test018 test019 test020 test021 test022 test023 test024 test025 test026
# test027 test028 test029 test030

.PHONY: check $(TESTS)
Expand Down
Binary file added regression/test002
Binary file not shown.
1 change: 1 addition & 0 deletions regression/test002.log
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
> > 5
31 changes: 31 additions & 0 deletions regression/test002.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
.data
x: .int 0
y: .int 0
z: .int 0
.text
.globl main
main:
pushl %ebp
movl %esp,%ebp
subl $0,%esp
call lread
movl %eax,x
call lread
movl %eax,y
movl y,%eax
movl y,%ebx
movl %eax,%edx
imull %ebx,%eax
movl %edx,%eax
movl %eax,z
movl x,%eax
movl z,%ebx
movl %eax,%edx
addl %ebx,%eax
movl %edx,%eax
pushl %eax
call lwrite
popl %edx
movl %ebp,%esp
popl %ebp
ret
Binary file added runtime/runtime.o
Binary file not shown.
54 changes: 28 additions & 26 deletions src/Driver.ml
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ open Expr
open Stmt
open Ostap

let parse filename =
let parse filename =
let s = Util.read filename in
Util.parse
(object
inherit Matcher.t s
inherit Util.Lexers.ident ["read"; "write"; "skip"] s
Util.parse
(object
inherit Matcher.t s
inherit Util.Lexers.ident ["read"; "write"; "skip"; "if"; "then"; "else"; "fi"; "while"; "do"; "od"; "for"; "elif"; "repeat"; "until"] s
inherit Util.Lexers.decimal s
inherit Util.Lexers.skip [
Matcher.Skip.whitespaces " \t\n";
Matcher.Skip.lineComment "--";
Matcher.Skip.nestedComment "(*" "*)"
Matcher.Skip.lineComment "--";
Matcher.Skip.nestedComment "(*" "*)"
] s
end)
(ostap (!(Stmt.parse) -EOF))
Expand All @@ -25,27 +25,29 @@ let main =
let to_compile = not (interpret || stack) in
let infile = Sys.argv.(if not to_compile then 2 else 1) in
match parse infile with

| `Ok prog ->
if to_compile
then
then
let basename = Filename.chop_suffix infile ".expr" in
ignore @@ X86.build prog basename
else
let rec read acc =
try
let r = read_int () in
Printf.printf "> ";
read (acc @ [r])
with End_of_file -> acc
in
let input = read [] in
let output =
if interpret
then Interpret.Program.eval prog input
else StackMachine.Interpret.run (StackMachine.Compile.Program.compile prog) input
in
List.iter (fun i -> Printf.printf "%d\n" i) output
| `Fail er -> Printf.eprintf "Syntax error: %s\n" er
with Invalid_argument _ ->
Printf.printf "Usage: rc [-i] <input file.expr>\n"
else
let rec read acc =
try
let r = read_int () in
Printf.printf "> ";
read (acc @ [r])
with End_of_file -> acc
in
let input = read [] in
let output =
if interpret
then Interpret.Program.eval prog input
else StackMachine.Interpret.run (StackMachine.Compile.Program.compile prog) input
in
List.iter (fun i -> Printf.printf "%d\n" i) output

| `Fail er -> Printf.eprintf "Syntax error: %s\n" er
with Invalid_argument _ ->
Printf.printf "Usage: rc [-i | -s] <input file.expr>\n";
Printf.printf "Example: cat test001.input | .././rc.native -s test001.expr\n"
16 changes: 13 additions & 3 deletions src/Interpret.ml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,17 @@ module Expr =
| Const z -> z
| Add (x, y) -> eval' x + eval' y
| Mul (x, y) -> eval' x * eval' y

| Sub (x, y) -> eval' x - eval' y
| Div (x, y) -> eval' x / eval' y
| Mod (x, y) -> eval' x mod eval' y
| And (x, y) -> if( (eval' x) == 1 && (eval' y) == 1) then 1 else 0
| Or (x, y) -> if( (eval' x) == 0 && (eval' y) == 0) then 0 else 1
| Equals (x, y) -> if( (eval' x) == (eval' y)) then 1 else 0
| NotEquals (x, y) -> if( (eval' x) == (eval' y)) then 0 else 1
| Greater (x, y) -> if( (eval' x) > (eval' y)) then 1 else 0
| Less (x, y) -> if( (eval' x) < (eval' y)) then 1 else 0
| GreaterEquals (x, y) -> if( (eval' x) < (eval' y)) then 0 else 1
| LessEquals (x, y) -> if( (eval' x) > (eval' y)) then 0 else 1
end

(* Interpreter for statements *)
Expand All @@ -30,8 +40,8 @@ module Stmt =
| Skip -> conf
| Assign (x, e) -> (update st x (Expr.eval e st), input, output)
| Read x ->
let z :: input' = input in
(update st x z, input', output)
let z :: input' = input in
(update st x z, input', output)
| Write e -> (st, input, output @ [Expr.eval e st])
| Seq (s1, s2) -> eval s1 conf |> eval s2

Expand Down
64 changes: 49 additions & 15 deletions src/Language.ml
Original file line number Diff line number Diff line change
@@ -1,21 +1,55 @@
open Ostap.Util

(* AST for expressions *)
module Expr =
struct

type t =
| Var of string
| Const of int
| Add of t * t
| Mul of t * t
| Var of string
| Const of int
| Add of t * t
| Mul of t * t
| Sub of t * t
| Div of t * t
| Mod of t * t
| And of t * t
| Or of t * t
| Equals of t * t
| NotEquals of t * t
| Greater of t * t
| Less of t * t
| GreaterEquals of t * t
| LessEquals of t * t



let rec parser_ s =
expr id
[|
`Nona , [ostap ("||"), (fun x y -> Or (x, y))];
`Nona , [ostap ("&&"), (fun x y -> And (x, y))];
`Nona , [ostap ("=="), (fun x y -> Equals (x, y));
ostap ("!="), (fun x y -> NotEquals (x, y));
ostap (">"), (fun x y -> Greater (x, y));
ostap ("<"), (fun x y -> Less (x, y));
ostap (">="), (fun x y -> GreaterEquals (x, y));
ostap ("<="), (fun x y -> LessEquals (x, y));];

`Lefta , [ostap ("+"), (fun x y -> Add (x, y));
ostap ("-"), (fun x y -> Sub (x, y))];

`Lefta , [ostap ("*"), (fun x y -> Mul (x, y));
ostap ("/"), (fun x y -> Div (x, y));
ostap ("%"), (fun x y -> Mod (x, y))]
|]
primary s
and
ostap (
primary:
n:DECIMAL {Const n}
| e:IDENT {Var e}
| -"(" parser_ -")")

ostap (
parse: x:mull "+" y:parse {Add (x,y)} | mull;
mull : x:prim "*" y:mull {Mul (x,y)} | prim;
prim :
n:DECIMAL {Const n}
| e:IDENT {Var e}
| -"(" parse -")"
)

end

Expand All @@ -30,12 +64,12 @@ module Stmt =
| Write of Expr.t
| Seq of t * t

let expr = Expr.parse
let expr_parser = Expr.parser_

ostap (
simp: x:IDENT ":=" e:expr {Assign (x, e)}
simp: x:IDENT ":=" e:expr_parser {Assign (x, e)}
| %"read" "(" x:IDENT ")" {Read x}
| %"write" "(" e:expr ")" {Write e}
| %"write" "(" e:expr_parser ")" {Write e}
| %"skip" {Skip};

parse: s:simp ";" d:parse {Seq (s,d)} | simp
Expand Down
77 changes: 59 additions & 18 deletions src/StackMachine.ml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,17 @@ module Instr =
| ST of string
| ADD
| MUL

| SUB
| DIV
| MOD
| AND
| OR
| EQUALS
| NOT_EQUALS
| GREATER
| LESS
| GREATER_EQUALS
| LESS_EQUALS
end

module Program =
Expand All @@ -26,31 +36,50 @@ module Interpret =
open Instr
open Interpret.Stmt





let run prg input =
let rec run' prg ((stack, st, input, output) as conf) =
let rec run' ((prg,stack, st, input, output) as conf) =
match prg with
| [] -> conf
| i :: prg' ->
run' prg' (
run'(
match i with
| READ -> let z :: input' = input in
(z :: stack, st, input', output)
| WRITE -> let z :: stack' = stack in
(stack', st, input, output @ [z])
| PUSH n -> (n :: stack, st, input, output)
| LD x -> (st x :: stack, st, input, output)
| ST x -> let z :: stack' = stack in
(stack', update st x z, input, output)
| _ -> let y :: x :: stack' = stack in
((match i with ADD -> (+) | _ -> ( * )) x y :: stack',
(prg',z :: stack, st, input', output)
| WRITE -> let h :: stack' = stack in
(prg',stack', st, input, output @ [h])
| PUSH n -> (prg',n :: stack, st, input, output)
| LD x -> (prg',st x :: stack, st, input, output)
| ST x -> let h :: stack' = stack in
(prg',stack', update st x h, input, output)

| _ -> let y :: x :: stack'' = stack in
(prg',(match i with
| ADD -> ( + )
| MUL -> ( * )
| SUB -> ( - )
| DIV -> ( / )
| MOD -> ( mod )
| AND -> ( fun a b -> if (a == 1) && (b == 1) then 1 else 0)
| OR -> ( fun a b -> if (a == 0) && (b == 0) then 0 else 1)
| EQUALS -> ( fun a b -> if (a == b) then 1 else 0)
| NOT_EQUALS -> ( fun a b -> if (a == b) then 0 else 1)
| GREATER -> ( fun a b -> if (a > b) then 1 else 0)
| LESS -> ( fun a b -> if (a < b) then 1 else 0)
| GREATER_EQUALS -> ( fun a b -> if (a < b) then 0 else 1)
| LESS_EQUALS -> ( fun a b -> if (a > b) then 0 else 1)
) x y :: stack'',
st,
input,
output
)
)
in
let (_, _, _, output) =
run' prg ([],
let (_,_, _, _, output) =
run' (prg,[],
(fun _ -> failwith "undefined variable"),
input,
[]
Expand All @@ -69,12 +98,24 @@ module Compile =

open Language.Expr

let rec compile = function
let rec compile =
let twoargs op (x,y) = (compile x) @ (compile y) @ [op] in
function
| Var x -> [LD x]
| Const n -> [PUSH n]
| Add (x, y) -> (compile x) @ (compile y) @ [ADD]
| Mul (x, y) -> (compile x) @ (compile y) @ [MUL]

| Add (x, y) -> twoargs ADD (x, y)
| Mul (x, y) -> twoargs MUL (x, y)
| Sub (x, y) -> twoargs SUB (x, y)
| Div (x, y) -> twoargs DIV (x, y)
| Mod (x, y) -> twoargs MOD (x, y)
| And (x, y) -> twoargs AND (x, y)
| Or (x, y) -> twoargs OR (x, y)
| Equals (x, y) -> twoargs EQUALS (x, y)
| NotEquals (x, y) -> twoargs NOT_EQUALS (x, y)
| Greater (x, y) -> twoargs GREATER (x, y)
| Less (x, y) -> twoargs LESS (x, y)
| GreaterEquals (x, y) -> twoargs GREATER_EQUALS (x, y)
| LessEquals (x, y) -> twoargs LESS_EQUALS (x, y)
end

module Stmt =
Expand Down
Loading