diff --git a/rc.byte b/rc.byte
new file mode 120000
index 00000000..f5dacbdf
--- /dev/null
+++ b/rc.byte
@@ -0,0 +1 @@
+/home/sl0n/Documents/DvlpngLnggPrcsss/eltech_compilers/_build/src/rc.byte
\ No newline at end of file
diff --git a/rc.native b/rc.native
new file mode 120000
index 00000000..d40d8b8e
--- /dev/null
+++ b/rc.native
@@ -0,0 +1 @@
+/home/sl0n/Documents/DvlpngLnggPrcsss/eltech_compilers/_build/src/rc.native
\ No newline at end of file
diff --git a/regression/Makefile b/regression/Makefile
index bbecbbd4..30a20692 100644
--- a/regression/Makefile
+++ b/regression/Makefile
@@ -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)
diff --git a/regression/test002 b/regression/test002
new file mode 100755
index 00000000..f2b3dadd
Binary files /dev/null and b/regression/test002 differ
diff --git a/regression/test002.log b/regression/test002.log
new file mode 100644
index 00000000..c87a5cf3
--- /dev/null
+++ b/regression/test002.log
@@ -0,0 +1 @@
+> > 5
diff --git a/regression/test002.s b/regression/test002.s
new file mode 100644
index 00000000..b50bd318
--- /dev/null
+++ b/regression/test002.s
@@ -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
diff --git a/runtime/runtime.o b/runtime/runtime.o
new file mode 100644
index 00000000..ea3478ab
Binary files /dev/null and b/runtime/runtime.o differ
diff --git a/src/Driver.ml b/src/Driver.ml
index 5c8e0b34..d8d009b5 100644
--- a/src/Driver.ml
+++ b/src/Driver.ml
@@ -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))
@@ -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] \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] \n";
+Printf.printf "Example: cat test001.input | .././rc.native -s test001.expr\n"
diff --git a/src/Interpret.ml b/src/Interpret.ml
index 9f863d55..f5ba4bee 100644
--- a/src/Interpret.ml
+++ b/src/Interpret.ml
@@ -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 *)
@@ -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
diff --git a/src/Language.ml b/src/Language.ml
index 96ac3e01..70c1d367 100644
--- a/src/Language.ml
+++ b/src/Language.ml
@@ -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
@@ -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
diff --git a/src/StackMachine.ml b/src/StackMachine.ml
index 870537a4..1b586735 100644
--- a/src/StackMachine.ml
+++ b/src/StackMachine.ml
@@ -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 =
@@ -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,
[]
@@ -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 =
diff --git a/src/X86.ml b/src/X86.ml
index 9f0544af..b3c11e29 100644
--- a/src/X86.ml
+++ b/src/X86.ml
@@ -6,16 +6,31 @@ type opnd = R of int | S of int | L of int | M of string
let regs = [|"%eax"; "%ebx"; "%ecx"; "%esi"; "%edi"; "%edx"; "%esp"; "%ebp"|]
let nregs = Array.length regs - 3
+
+let [|al; dl|] = [|"%al"; "%dl"|]
+
let [|eax; ebx; ecx; esi; edi; edx; esp; ebp|] = Array.mapi (fun i _ -> R i) regs
type instr =
| Add of opnd * opnd
+| Sub of opnd * opnd
+| Div of opnd
+| Cltd
| Mul of opnd * opnd
| Mov of opnd * opnd
| Push of opnd
| Pop of opnd
| Call of string
| Ret
+| AndBin of opnd *opnd
+| OrBin of opnd *opnd
+| Cmp of opnd *opnd
+| Setg of string
+| Setl of string
+| Sete of string
+| Setne of string
+| Setge of string
+| Setle of string
let to_string buf code =
let instr =
@@ -33,6 +48,18 @@ let to_string buf code =
| Pop x -> Printf.sprintf "popl\t%s" (opnd x)
| Call x -> Printf.sprintf "call\t%s" x
| Ret -> "ret"
+ | Cltd -> "cltd"
+ | Sub (x, y) -> Printf.sprintf "subl\t%s,%s" (opnd x) (opnd y)
+ | Div x -> Printf.sprintf "idiv\t%s" (opnd x)
+ | AndBin (x, y) -> Printf.sprintf "andl\t%s,%s" (opnd x) (opnd y)
+ | OrBin (x, y) -> Printf.sprintf "orl\t%s,%s" (opnd x) (opnd y)
+ | Cmp (x, y) -> Printf.sprintf "cmpl\t%s,%s" (opnd x) (opnd y)
+ | Setg x -> Printf.sprintf "setg\t%s" x
+ | Setl x -> Printf.sprintf "setl\t%s" x
+ | Sete x -> Printf.sprintf "sete\t%s" x
+ | Setne x -> Printf.sprintf "setne\t%s" x
+ | Setge x -> Printf.sprintf "setge\t%s" x
+ | Setle x -> Printf.sprintf "setle\t%s" x
in
let out s =
Buffer.add_string buf "\t";
@@ -81,16 +108,32 @@ let rec sint env prg sstack =
| WRITE ->
env, [Push eax; Call "lwrite"; Pop edx], []
| _ ->
- let x::(y::_ as sstack') = sstack in
- (fun op ->
- match x, y with
- | S _, S _ -> env, [Mov (y, edx); op x edx; Mov (edx, y)], sstack'
- | _ -> env, [op x y], sstack'
- )
+
+ let x::(y::_ as sstack') = sstack in
+ let andop = [Mov (y, edx); AndBin (y, edx); (*compare y with self*)
+ Mov (L 0, edx); Setne dl; (*put result in edx*)
+ Mov (x, eax); AndBin (x, eax); (*compare x with self*)
+ Mov (L 0, eax); Setne al; (*put result in eax*)
+ AndBin (eax, edx); Mov (L 0, edx); Setne dl; (*compare eax with edx and put result in edx*)
+Mov (edx, y)] in
+ let short codearr = env, [Mov (y, edx)] @ codearr @ [Mov (edx, y)], sstack' in
+ let shorteq setop = short ([Cmp(x, y); Mov (L 0, edx)] @ setop @ [Mov (edx, y)]) in
(match i with
- | MUL -> fun x y -> Mul (x, y)
- | ADD -> fun x y -> Add (x, y)
- )
+ (* | MUL -> fun (x, y) -> Mul (x, y) *)
+ | MUL -> short [Mul(x,y)]
+ | ADD -> short [Add (x, y)]
+ | DIV -> env, [Mov (y, eax); Cltd; Div x; Mov (eax, y)], sstack'
+ | SUB -> short [Sub(x, edx)]
+ | MOD -> env, [Mov (y, eax); Cltd; Div x; Mov (edx, y)], sstack'
+ | OR -> short [OrBin(x, edx); Mov (L 0, edx); Setne dl]
+ | AND -> env, andop, sstack'
+ | EQUALS -> shorteq [Sete dl]
+ | NOT_EQUALS -> shorteq [Setne dl]
+ | GREATER -> shorteq [Setg dl]
+ | LESS -> shorteq [Setl dl]
+ | GREATER_EQUALS -> shorteq [Setge dl]
+ | LESS_EQUALS -> shorteq [Setle dl]
+ )
in
let env, code', sstack'' = sint env prg' sstack' in
env, code @ code', sstack''