feat: Implement eval methods for expressions

This commit is contained in:
Lucàs
2024-10-26 22:40:50 +02:00
parent b493c77d70
commit 9e201e8d16
28 changed files with 638 additions and 325 deletions
+2 -2
View File
@@ -1,7 +1,7 @@
(library
(name Analyzer)
(name analyzer)
(modules lexer parser)
(libraries Syntax))
(libraries syntax))
(menhir
(modules parser))
+12 -3
View File
@@ -33,7 +33,8 @@ rule token = parse
| '+' { PLUS }
| '-' { MINUS }
| '*' { TIMES }
| '/' { DIV }
| '/' { DIVIDE }
| "=" { EQUAL }
| "==" { EQUAL_EQUAL }
| "!=" { NOT_EQUAL }
| "<" { LESS_THAN }
@@ -43,16 +44,24 @@ rule token = parse
| "&&" { AMPERSAND_AMPERSAND }
| "||" { BAR_BAR }
| "!" { EXCLAMATION }
| ":" { COLON }
(* Keywords *)
| "vrai" { BOOLEAN(true) }
| "faux" { BOOLEAN(false) }
| "var" { VAR }
| "entier" { INTEGER_TYPE }
| "flottant" { FLOAT_TYPE }
| "booleen" { BOOLEAN_TYPE }
| "chaine" { STRING_TYPE }
| "caractere" { CHARACTER_TYPE }
| "nul" { NULL_TYPE }
| "vide" { VOID_TYPE }
(* Literals *)
| interger as i { INT (int_of_string i) }
| interger as i { INTEGER (int_of_string i) }
| float as f { FLOAT (float_of_string f) }
| '"' { Buffer.clear buffer; STRING(string lexbuf) }
| "''" { NULL }
| "'\\''" { CHARACTER '\'' }
| "'\\n'" { CHARACTER '\n' }
| "'\\t'" { CHARACTER '\t' }
+50 -29
View File
@@ -2,18 +2,28 @@
open Syntax
%}
%token <int> INT
%token <int> INTEGER
%token <float> FLOAT
%token <char> CHARACTER
%token <bool> BOOLEAN
%token <string> STRING
%token <string> IDENTIFIER
%token NULL
%token EQUAL "="
%token VAR
%token INTEGER_TYPE
%token FLOAT_TYPE
%token BOOLEAN_TYPE
%token STRING_TYPE
%token CHARACTER_TYPE
%token NULL_TYPE
%token VOID_TYPE
%token PLUS "+"
%token MINUS "-"
%token TIMES "*"
%token DIV "/"
%token DIVIDE "/"
%token EQUAL_EQUAL "=="
%token NOT_EQUAL "!="
%token LESS_THAN "<"
@@ -25,6 +35,7 @@ open Syntax
%token EXCLAMATION "!"
%token SEMICOLON ";"
%token COLON ":"
%token LPAREN "("
%token RPAREN ")"
@@ -36,49 +47,59 @@ open Syntax
%nonassoc UMINUS
%start <SourceFiles.source_files> main
%start <Roots.program> main
%%
main:
| statements EOF { SourceFiles.SourceFile $1 }
| statements EOF { new Roots.program $1 }
statements:
| statement ";" { $1 }
| statement ";" statements { Statements.SequenceStatement ($1, $3) }
| statement ";" statements { new Statements.sequence $1 $3 }
statement:
| expression { Statements.ExpressionStatement($1) }
| expression { new Statements.expression $1 }
| VAR IDENTIFIER ":" tp "=" expression { new Statements.variableDeclaration $2 $4 $6 }
expression:
| literal { Expressions.Literal($1) }
| IDENTIFIER { Expressions.Identifier($1) }
| literal { new Expressions.literal $1 }
| IDENTIFIER { new Expressions.identifier $1 }
| unary_expression { $1 }
| binary_expression { $1 }
| "(" expression ")" { $2 }
tp:
| INTEGER_TYPE { Types.IntegerType }
| FLOAT_TYPE { Types.FloatType }
| BOOLEAN_TYPE { Types.BooleanType }
| STRING_TYPE { Types.StringType }
| CHARACTER_TYPE { Types.CharacterType }
| NULL_TYPE { Types.NullType }
| VOID_TYPE { Types.VoidType }
literal:
| INT { Literals.Integer($1) }
| FLOAT { Literals.Float($1) }
| BOOLEAN { Literals.Boolean($1) }
| CHARACTER { Literals.Character($1) }
| STRING { Literals.String($1) }
| NULL { Literals.Null }
| INTEGER { new Literals.eInteger $1 }
| FLOAT { new Literals.eFloat $1 }
| BOOLEAN { new Literals.eBoolean $1 }
| CHARACTER { new Literals.eCharacter $1 }
| STRING { new Literals.eString $1 }
| NULL_TYPE { new Literals.eNull }
unary_expression:
| "-" expression %prec UMINUS { Expressions.UnaryExpression(UnaryOperators.ArithmeticNegation, $2) }
| "!" expression { Expressions.UnaryExpression(UnaryOperators.LogicalNegation, $2) }
| "-" expression %prec UMINUS { new Expressions.unaryOperation (new UnaryOperators.arithmeticNegation) $2 }
| "!" expression { new Expressions.unaryOperation (new UnaryOperators.logicalNegation) $2 }
binary_expression:
| expression "+" expression { Expressions.BinaryExpression (BinaryOperators.Add, $1, $3) }
| expression "-" expression { Expressions.BinaryExpression (BinaryOperators.Subtract, $1, $3) }
| expression "*" expression { Expressions.BinaryExpression (BinaryOperators.Multiply, $1, $3) }
| expression "/" expression { Expressions.BinaryExpression (BinaryOperators.Divide, $1, $3) }
| expression "==" expression { Expressions.BinaryExpression (BinaryOperators.Equals, $1, $3) }
| expression "!=" expression { Expressions.BinaryExpression (BinaryOperators.NotEquals, $1, $3) }
| expression "<" expression { Expressions.BinaryExpression (BinaryOperators.LessThan, $1, $3) }
| expression "<=" expression { Expressions.BinaryExpression (BinaryOperators.LessThanEquals, $1, $3) }
| expression ">" expression { Expressions.BinaryExpression (BinaryOperators.GreaterThan, $1, $3) }
| expression ">=" expression { Expressions.BinaryExpression (BinaryOperators.GreaterThanEquals, $1, $3) }
| expression "&&" expression { Expressions.BinaryExpression (BinaryOperators.And, $1, $3) }
| expression "||" expression { Expressions.BinaryExpression (BinaryOperators.Or, $1, $3) }
| expression "+" expression { new Expressions.binaryOperation (new BinaryOperators.add) $1 $3 }
| expression "-" expression { new Expressions.binaryOperation (new BinaryOperators.subtract) $1 $3 }
| expression "*" expression { new Expressions.binaryOperation (new BinaryOperators.multiply) $1 $3 }
| expression "/" expression { new Expressions.binaryOperation (new BinaryOperators.divide) $1 $3 }
| expression "==" expression { new Expressions.binaryOperation (new BinaryOperators.equals) $1 $3 }
| expression "!=" expression { new Expressions.binaryOperation (new BinaryOperators.notEquals) $1 $3 }
| expression "<" expression { new Expressions.binaryOperation (new BinaryOperators.lessThan) $1 $3 }
| expression "<=" expression { new Expressions.binaryOperation (new BinaryOperators.lessThanEquals) $1 $3 }
| expression ">" expression { new Expressions.binaryOperation (new BinaryOperators.greaterThan) $1 $3 }
| expression ">=" expression { new Expressions.binaryOperation (new BinaryOperators.greaterThanEquals) $1 $3 }
| expression "&&" expression { new Expressions.binaryOperation (new BinaryOperators.logicalAnd) $1 $3 }
| expression "||" expression { new Expressions.binaryOperation (new BinaryOperators.logicalOr) $1 $3 }
-1
View File
@@ -1 +0,0 @@
type environment = { variables : (string * Types.types) list }
+1 -1
View File
@@ -1,3 +1,3 @@
(library
(name Croissant)
(libraries Syntax Analyzer))
(libraries syntax analyzer))
+264 -26
View File
@@ -1,27 +1,265 @@
type binary_operators =
| Add
| Subtract
| Multiply
| Divide
| Equals
| NotEquals
| LessThan
| LessThanEquals
| GreaterThan
| GreaterThanEquals
| And
| Or
class virtual binaryOperator =
object
inherit Node.node
method virtual check_type : Types.t * Types.t -> Types.t
let pp_binary_operators = function
| Add -> "Add"
| Subtract -> "Subtract"
| Multiply -> "Multiply"
| Divide -> "Divide"
| Equals -> "Equals"
| NotEquals -> "NotEquals"
| LessThan -> "LessThan"
| LessThanEquals -> "LessThanEquals"
| GreaterThan -> "GreaterThan"
| GreaterThanEquals -> "GreaterThanEquals"
| And -> "And"
| Or -> "Or"
method virtual eval
: Literals.literal_value * Literals.literal_value ->
Literals.literal_value
end
class add =
object
inherit binaryOperator
method to_string = "Add"
method check_type (left, right) =
match (left, right) with
| Types.IntegerType, Types.IntegerType -> Types.IntegerType
| Types.FloatType, Types.FloatType -> Types.FloatType
| Types.FloatType, Types.IntegerType -> Types.FloatType
| Types.IntegerType, Types.FloatType -> Types.FloatType
| Types.StringType, Types.StringType -> Types.StringType
| _ -> raise (Failure "Add: operands must be numbers")
method eval (left, right) =
match (left, right) with
| `Int a, `Int b -> `Int (a + b)
| `Float a, `Float b -> `Float (a +. b)
| `Float a, `Int b -> `Float (a +. float_of_int b)
| `Int a, `Float b -> `Float (float_of_int a +. b)
| `String a, `String b -> `String (a ^ b) (* Concatenation *)
| _ -> raise (Failure "Add: operands must be numbers")
end
class subtract =
object
inherit binaryOperator
method to_string = "Subtract"
method check_type (left, right) =
match (left, right) with
| Types.IntegerType, Types.IntegerType -> Types.IntegerType
| Types.FloatType, Types.FloatType -> Types.FloatType
| Types.FloatType, Types.IntegerType -> Types.FloatType
| Types.IntegerType, Types.FloatType -> Types.FloatType
| _ -> raise (Failure "Subtract: operands must be numbers")
method eval (left, right) =
match (left, right) with
| `Int a, `Int b -> `Int (a - b)
| `Float a, `Float b -> `Float (a -. b)
| `Float a, `Int b -> `Float (a -. float_of_int b)
| `Int a, `Float b -> `Float (float_of_int a -. b)
| _ -> raise (Failure "Subtract: operands must be numbers")
end
class multiply =
object
inherit binaryOperator
method to_string = "Multiply"
method check_type (left, right) =
match (left, right) with
| Types.IntegerType, Types.IntegerType -> Types.FloatType
| Types.FloatType, Types.FloatType -> Types.FloatType
| Types.FloatType, Types.IntegerType -> Types.FloatType
| Types.IntegerType, Types.FloatType -> Types.FloatType
| _ -> raise (Failure "Multiply: operands must be numbers")
method eval (left, right) =
match (left, right) with
| `Int a, `Int b -> `Float (float_of_int a *. float_of_int b)
| `Float a, `Float b -> `Float (a *. b)
| `Float a, `Int b -> `Float (a *. float_of_int b)
| `Int a, `Float b -> `Float (float_of_int a *. b)
| _ -> raise (Failure "Multiply: operands must be numbers")
end
class divide =
object
inherit binaryOperator
method to_string = "Divide"
method check_type (left, right) =
match (left, right) with
| Types.IntegerType, Types.IntegerType -> Types.FloatType
| Types.FloatType, Types.FloatType -> Types.FloatType
| Types.FloatType, Types.IntegerType -> Types.FloatType
| Types.IntegerType, Types.FloatType -> Types.FloatType
| _ -> raise (Failure "Divide: operands must be numbers")
method eval (left, right) =
match (left, right) with
| `Int a, `Int b -> `Float (float_of_int a /. float_of_int b)
| `Float a, `Float b -> `Float (a /. b)
| `Float a, `Int b -> `Float (a /. float_of_int b)
| `Int a, `Float b -> `Float (float_of_int a /. b)
| _ -> raise (Failure "Divide: operands must be numbers")
end
class equals =
object
inherit binaryOperator
method to_string = "Equals"
method check_type (left, right) =
if left = right then Types.BooleanType
else raise (Failure "Equals: operands must have the same type")
method eval (left, right) =
match (left, right) with
| `Int a, `Int b -> `Bool (a = b)
| `Float a, `Float b -> `Bool (a = b)
| `Float a, `Int b -> `Bool (a = float_of_int b)
| `Int a, `Float b -> `Bool (float_of_int a = b)
| `String a, `String b -> `Bool (a = b)
| `Bool a, `Bool b -> `Bool (a = b)
| `Char a, `Char b -> `Bool (a = b)
| `Null, `Null -> `Bool true
| `Void, `Void -> `Bool true
| _ -> raise (Failure "Equals: operands must have the same type")
end
class notEquals =
object
inherit binaryOperator
method to_string = "NotEquals"
method check_type (left, right) =
if left = right then Types.BooleanType
else raise (Failure "Equals: operands must have the same type")
method eval (left, right) =
match (left, right) with
| `Int a, `Int b -> `Bool (a <> b)
| `Float a, `Float b -> `Bool (a <> b)
| `Float a, `Int b -> `Bool (a <> float_of_int b)
| `Int a, `Float b -> `Bool (float_of_int a <> b)
| `String a, `String b -> `Bool (a <> b)
| `Bool a, `Bool b -> `Bool (a <> b)
| `Char a, `Char b -> `Bool (a <> b)
| `Null, `Null -> `Bool false
| `Void, `Void -> `Bool false
| _ -> raise (Failure "NotEquals: operands must have the same type")
end
class lessThan =
object
inherit binaryOperator
method to_string = "LessThan"
method check_type (left, right) =
match (left, right) with
| Types.IntegerType, Types.IntegerType -> Types.BooleanType
| Types.FloatType, Types.FloatType -> Types.BooleanType
| Types.FloatType, Types.IntegerType -> Types.BooleanType
| Types.IntegerType, Types.FloatType -> Types.BooleanType
| _ -> raise (Failure "LessThan: operands must be numbers")
method eval (left, right) =
match (left, right) with
| `Int a, `Int b -> `Bool (a < b)
| `Float a, `Float b -> `Bool (a < b)
| `Float a, `Int b -> `Bool (a < float_of_int b)
| `Int a, `Float b -> `Bool (float_of_int a < b)
| _ -> raise (Failure "LessThan: operands must be numbers")
end
class lessThanEquals =
object
inherit binaryOperator
method to_string = "LessThanEquals"
method check_type (left, right) =
match (left, right) with
| Types.IntegerType, Types.IntegerType -> Types.BooleanType
| Types.FloatType, Types.FloatType -> Types.BooleanType
| Types.FloatType, Types.IntegerType -> Types.BooleanType
| Types.IntegerType, Types.FloatType -> Types.BooleanType
| _ -> raise (Failure "LessThanEquals: operands must be numbers")
method eval (left, right) =
match (left, right) with
| `Int a, `Int b -> `Bool (a <= b)
| `Float a, `Float b -> `Bool (a <= b)
| `Float a, `Int b -> `Bool (a <= float_of_int b)
| `Int a, `Float b -> `Bool (float_of_int a <= b)
| _ -> raise (Failure "LessThanEquals: operands must be numbers")
end
class greaterThan =
object
inherit binaryOperator
method to_string = "GreaterThan"
method check_type (left, right) =
match (left, right) with
| Types.IntegerType, Types.IntegerType -> Types.BooleanType
| Types.FloatType, Types.FloatType -> Types.BooleanType
| Types.FloatType, Types.IntegerType -> Types.BooleanType
| Types.IntegerType, Types.FloatType -> Types.BooleanType
| _ -> raise (Failure "GreaterThan: operands must be numbers")
method eval (left, right) =
match (left, right) with
| `Int a, `Int b -> `Bool (a > b)
| `Float a, `Float b -> `Bool (a > b)
| `Float a, `Int b -> `Bool (a > float_of_int b)
| `Int a, `Float b -> `Bool (float_of_int a > b)
| _ -> raise (Failure "GreaterThan: operands must be numbers")
end
class greaterThanEquals =
object
inherit binaryOperator
method to_string = "GreaterThanEquals"
method check_type (left, right) =
match (left, right) with
| Types.IntegerType, Types.IntegerType -> Types.BooleanType
| Types.FloatType, Types.FloatType -> Types.BooleanType
| Types.FloatType, Types.IntegerType -> Types.BooleanType
| Types.IntegerType, Types.FloatType -> Types.BooleanType
| _ -> raise (Failure "GreaterThanEquals: operands must be numbers")
method eval (left, right) =
match (left, right) with
| `Int a, `Int b -> `Bool (a >= b)
| `Float a, `Float b -> `Bool (a >= b)
| `Float a, `Int b -> `Bool (a >= float_of_int b)
| `Int a, `Float b -> `Bool (float_of_int a >= b)
| _ -> raise (Failure "GreaterThanEquals: operands must be numbers")
end
class logicalAnd =
object
inherit binaryOperator
method to_string = "And"
method check_type (left, right) =
match (left, right) with
| Types.BooleanType, Types.BooleanType -> Types.BooleanType
| _ -> raise (Failure "And: operands must be numbers")
method eval (left, right) =
match (left, right) with
| `Bool a, `Bool b -> `Bool (a && b)
| _ -> raise (Failure "And: operands must be booleans")
end
class logicalOr =
object
inherit binaryOperator
method to_string = "Or"
method check_type (left, right) =
match (left, right) with
| Types.BooleanType, Types.BooleanType -> Types.BooleanType
| _ -> raise (Failure "Or: operands must be numbers")
method eval (left, right) =
match (left, right) with
| `Bool a, `Bool b -> `Bool (a || b)
| _ -> raise (Failure "Or: operands must be booleans")
end
+27
View File
@@ -0,0 +1,27 @@
class evalEnvironment =
object
val mutable env : (string, Literals.literal_value) Hashtbl.t =
Hashtbl.create 10
method add (name : string) (lit : Literals.literal_value) =
Hashtbl.add env name lit
method find (name : string) = Hashtbl.find env name
method clone : evalEnvironment =
let new_env = new evalEnvironment in
Hashtbl.iter (fun k v -> new_env#add k v) env;
new_env
end
class typeEnvironments =
object
val mutable env : (string, Types.t) Hashtbl.t = Hashtbl.create 10
method add (name : string) (tp : Types.t) = Hashtbl.add env name tp
method find (name : string) = Hashtbl.find env name
method clone : typeEnvironments =
let new_env = new typeEnvironments in
Hashtbl.iter (fun k v -> new_env#add k v) env;
new_env
end
+57 -21
View File
@@ -1,23 +1,59 @@
open Literals
open UnaryOperators
open BinaryOperators
class virtual expression =
object
inherit Node.node
method virtual check_type : Environments.typeEnvironments -> Types.t
method virtual eval : Environments.evalEnvironment -> Literals.literal_value
end
type expressions =
| Literal of literals
| Identifier of string
| UnaryExpression of unary_operators * expressions
| BinaryExpression of binary_operators * expressions * expressions
class literal (lit : Literals.literal) =
object
inherit expression
method to_string = "Literal(" ^ lit#to_string ^ ")"
method check_type _ = lit#check_type
method eval _ = lit#value
end
let rec pp_expressions = function
| Literal l ->
let pp_l = pp_literals l in
Printf.sprintf "Literal(%s)" pp_l
| Identifier i -> Printf.sprintf "Identifier(\"%s\")" i
| UnaryExpression (op, e) ->
let pp_op = pp_unary_operators op and pp_e = pp_expressions e in
Printf.sprintf "UnaryExpression(%s, %s)" pp_op pp_e
| BinaryExpression (op, e1, e2) ->
let pp_op = pp_binary_operators op
and pp_e1 = pp_expressions e1
and pp_e2 = pp_expressions e2 in
Printf.sprintf "BinaryExpression(%s, %s, %s)" pp_op pp_e1 pp_e2
class identifier (name : string) =
object
inherit expression
method to_string = "Identifier(" ^ name ^ ")"
method check_type env =
try env#find name
with Not_found ->
raise (Failure ("Identifier '" ^ name ^ "' not found"))
method eval env = env#find name
end
class unaryOperation (operator : UnaryOperators.unaryOperator)
(operand : expression) =
object
inherit expression
method to_string =
"UnaryOperation(" ^ operator#to_string ^ ", " ^ operand#to_string ^ ")"
method check_type env =
let operand_type = operand#check_type env in
operator#check_type operand_type
method eval env = operator#eval (operand#eval env)
end
class binaryOperation (operator : BinaryOperators.binaryOperator)
(left : expression) (right : expression) =
object
inherit expression
method to_string =
"BinaryOperation(" ^ operator#to_string ^ ", " ^ left#to_string ^ ", "
^ right#to_string ^ ")"
method check_type env =
let left_type = left#check_type env in
let right_type = right#check_type env in
operator#check_type (left_type, right_type)
method eval env = operator#eval (left#eval env, right#eval env)
end
+79 -14
View File
@@ -1,15 +1,80 @@
type literals =
| Integer of int
| Float of float
| Character of char
| String of string
| Boolean of bool
| Null
type literal_value =
[ `Int of int
| `Float of float
| `String of string
| `Bool of bool
| `Char of char
| `Null
| `Void ]
let pp_literals = function
| Integer i -> Printf.sprintf "Integer(%d)" i
| Float f -> Printf.sprintf "Float(%f)" f
| Character c -> Printf.sprintf "Character('%c')" c
| String s -> Printf.sprintf "String(\"%s\")" s
| Boolean b -> Printf.sprintf "Boolean(%b)" b
| Null -> "Null"
let string_of_literal_value = function
| `Int i -> string_of_int i
| `Float f -> string_of_float f
| `String s -> "\"" ^ s ^ "\""
| `Bool b -> string_of_bool b
| `Char c -> "'" ^ String.make 1 c ^ "'"
| `Null -> "null"
| `Void -> "void"
class virtual literal =
object
inherit Node.node
method virtual value : literal_value
method virtual check_type : Types.t
end
class eInteger (value : int) =
object
inherit literal
method value = `Int value
method to_string = "Integer(" ^ string_of_int value ^ ")"
method check_type = Types.IntegerType
end
class eFloat (value : float) =
object
inherit literal
method value = `Float value
method to_string : string = "Float(" ^ string_of_float value ^ ")"
method check_type = Types.FloatType
end
class eString (value : string) =
object
inherit literal
method value = `String value
method to_string = "String(\"" ^ value ^ "\")"
method check_type = Types.StringType
end
class eBoolean (value : bool) =
object
inherit literal
method value = `Bool value
method to_string = "Boolean(" ^ string_of_bool value ^ ")"
method check_type = Types.BooleanType
end
class eCharacter (value : char) =
object
inherit literal
method value = `Char value
method to_string = "Character(" ^ String.make 1 value ^ ")"
method check_type = Types.CharacterType
end
class eNull =
object
inherit literal
method value = `Null
method to_string = "Null"
method check_type = Types.NullType
end
class eVoid =
object
inherit literal
method value = `Void
method to_string = "Void"
method check_type = Types.VoidType
end
+6
View File
@@ -0,0 +1,6 @@
class virtual node =
object
method virtual to_string : string
(* method virtual check_type : Types.type_ *)
(* method virtual eval *)
end
+17
View File
@@ -0,0 +1,17 @@
class program (statement : Statements.statement) =
object
inherit Node.node
method to_string = "Program(" ^ statement#to_string ^ ")"
method check_type =
let env : Environments.typeEnvironments =
new Environments.typeEnvironments
in
statement#check_type env
method eval =
let env : Environments.evalEnvironment =
new Environments.evalEnvironment
in
statement#eval env
end
-8
View File
@@ -1,8 +0,0 @@
open Statements
type source_files = SourceFile of statements
let pp_source_files = function
| SourceFile stmts ->
let pp_stmt = pp_statements stmts in
Printf.sprintf "SourceFile(%s)" pp_stmt
+50 -11
View File
@@ -1,13 +1,52 @@
open Expressions
class virtual statement =
object
inherit Node.node
method virtual check_type : Environments.typeEnvironments -> Types.t
method virtual eval : Environments.evalEnvironment -> Literals.literal_value
end
type statements =
| SequenceStatement of statements * statements
| ExpressionStatement of expressions
class sequence (left : statement) (right : statement) =
object
inherit statement
let rec pp_statements = function
| SequenceStatement (stmt1, stmt2) ->
let pp_stmt1 = pp_statements stmt1 and pp_stmt2 = pp_statements stmt2 in
Printf.sprintf "SequenceStatement(%s, %s)" pp_stmt1 pp_stmt2
| ExpressionStatement expr ->
let pp_expr = pp_expressions expr in
Printf.sprintf "ExpressionStatement(%s)" pp_expr
method to_string =
"Sequence(" ^ left#to_string ^ ", " ^ right#to_string ^ ")"
method check_type env =
let _ = left#check_type env in
right#check_type env
method eval env =
let _ = left#eval env in
right#eval env
end
class expression (expression : Expressions.expression) =
object
inherit statement
method to_string = "Expression(" ^ expression#to_string ^ ")"
method check_type env = expression#check_type env
method eval env = expression#eval env
end
class variableDeclaration (name : string) (tp : Types.t)
(expression : Expressions.expression) =
object
inherit statement
method to_string =
"VariableDeclaration(" ^ name ^ ", " ^ Types.string_of_t tp ^ ", "
^ expression#to_string ^ ")"
method check_type env =
let expression_type = expression#check_type env in
if tp = expression_type then (
env#add name expression_type;
Types.VoidType)
else raise (Failure "VariableDeclaration: type mismatch")
method eval env =
let value = expression#eval env in
env#add name value;
value
end
+9 -7
View File
@@ -1,15 +1,17 @@
type types =
type t =
| IntegerType
| FloatType
| CharacterType
| StringType
| BooleanType
| StringType
| CharacterType
| NullType
| VoidType
let pp_types = function
let string_of_t = function
| IntegerType -> "IntegerType"
| FloatType -> "FloatType"
| CharacterType -> "CharacterType"
| StringType -> "StringType"
| BooleanType -> "BooleanType"
| VoidType -> "VoidType"
| StringType -> "StringType"
| CharacterType -> "CharacterType"
| NullType -> "NullType"
| VoidType -> "VoidType"
+39 -4
View File
@@ -1,5 +1,40 @@
type unary_operators = ArithmeticNegation | LogicalNegation
class virtual unaryOperator =
object
inherit Node.node
method virtual check_type : Types.t -> Types.t
method virtual eval : Literals.literal_value -> Literals.literal_value
end
let pp_unary_operators = function
| ArithmeticNegation -> "ArithmeticNegation"
| LogicalNegation -> "LogicalNegation"
class arithmeticNegation =
object
inherit unaryOperator
method to_string = "ArithmeticNegation"
method check_type (operand : Types.t) =
match operand with
| Types.IntegerType -> Types.IntegerType
| Types.FloatType -> Types.FloatType
| _ -> raise (Failure "ArithmeticNegation: operand must be a number")
method eval operand =
match operand with
| `Int i -> `Int (-i)
| `Float f -> `Float (-.f)
| _ -> raise (Failure "ArithmeticNegation: operand must be a number")
end
class logicalNegation =
object
inherit unaryOperator
method to_string = "LogicalNegation"
method check_type (operand : Types.t) =
match operand with
| Types.BooleanType -> Types.BooleanType
| _ -> raise (Failure "LogicalNegation: operand must be a boolean")
method eval operand =
match operand with
| `Bool b -> `Bool (not b)
| _ -> raise (Failure "LogicalNegation: operand must be a boolean")
end
+7 -3
View File
@@ -1,10 +1,14 @@
(library
(name Syntax)
(name syntax)
(modules
Node
Types
Literals
Environments
BinaryOperators
UnaryOperators
Literals
Expressions
Statements
SourceFiles))
Roots)
; (libraries typing)
)