11 let no_symbol = new_symbol_string
"none"
13 let keyword_inst = ["add"; "sub"; "div"; "mul"; "rem"; "min"; "max";
14 "f_add"; "f_sub"; "f_div"; "f_mul"; "f_rem"; "f_max"; "f_min";
15 "eq"; "neq"; "gt"; "lt"; "gte"; "lte"; "cmp";
16 "f_eq"; "f_neq"; "f_gt"; "f_lt"; "f_gte"; "f_lte"; "f_cmp";
17 "shl"; "ashr"; "lshr"; "and"; "or"; "xor"; "not"; "uminus"; "abs";
18 "f_uminus"; "f_abs"; "sin"; "cos"; "sqrt";
19 "f_2_uint8"; "f_2_uint16"; "f_2_uint32"; "f_2_uint64";
20 "f_2_int8"; "f_2_int16"; "f_2_int32"; "f_2_int64";
21 "f_2_float32"; "f_2_floot64"; "f_2_float80";
22 "i_2_float32"; "i_2_float64"; "i_2_float80";
23 "i_2_int8"; "i_2_int16"; "i_2_int32"; "i_2_int64";
24 "i_2_uint8"; "i_2_uint16"; "i_2_uint32"; "i_2_uint64";
26 "goto"; "call"; "callex"; "extern";
30 let keyword_operator = ["$"; "."; ":"; ","; "("; ")"; "{"; "}"; "["; "]"; "="; "..."]
32 let keyword_word = ["function"; "data"; "datasize"; "init"; "as"; "empty"; "imports"; "exports";
35 let keyword_type = ["char"; "string";
36 "int8"; "int16"; "int32"; "int64";
37 "uint8"; "uint16"; "uint32"; "uint64";
38 "float32"; "float64"; "float80";
42 let keyword = keyword_inst @ keyword_operator @ keyword_type @ keyword_word
44 let lexer = make_lexer
keyword
50 * This function is the brains of the bytecode parser. It is responsible for
51 * creating the program given a stream. Based on the header that is read by
52 * this function, it calls its helper functions to construct the specified
55 let rec prog_of_stream prog stream
=
56 let pos = "prog_of_stream: " in
59 match type_token_of_stream stream
with
61 let prog = datasize_of_stream
prog stream
in
62 prog_of_stream prog stream
64 let prog = data_of_stream
prog stream
in
65 prog_of_stream prog stream
67 let prog = function_of_stream
prog stream
in
68 prog_of_stream prog stream
70 let prog = imports_of_stream
prog stream
in
71 prog_of_stream prog stream
73 let prog = exports_of_stream
prog stream
in
74 prog_of_stream prog stream
76 failwith
(pos ^
"undefined section header (" ^
(string_of_token header
) ^
")")
78 Stream.Failure
-> prog
79 | Stream.Error err
-> failwith
(pos ^ err
)
85 * The datasize section of the bytecode is constructed with this function
86 * and is added to the program structure.
88 and datasize_of_stream
prog stream
=
89 let size = value_of_stream stream
in
94 byte_data
= spset_set_spill_count
prog.byte_data i
;
96 | _
-> failwith
"datasize_of_stream: expected an integer"
98 and data_of_stream
prog stream
=
99 let pos = "data_of_stream: " in
100 let dt = type_token_of_stream stream
in
115 | Kwd
("float80") as ty
->
116 let addy = addy_of_stream stream
in
117 let val'
= value_of_stream stream
in
118 let v = as_var_of_stream stream
in
120 let dt = data_type_of_token
val' ty
in
122 let prog = { prog with
123 byte_global
= SymbolTable.add
prog.byte_global
v dt;
124 byte_data
= spset_add
prog.byte_data
v addy dt;
126 data_of_stream
prog stream
128 (* let prog = ptr_of_stream prog stream in *)
129 data_of_stream
prog stream
131 let prog = tuple_of_stream
prog stream
in
132 data_of_stream
prog stream
134 (* let prog = array_of_stream prog stream in *)
135 data_of_stream
prog stream
139 failwith
(pos ^
"invalid data type")
141 and imports_of_stream
prog stream
=
142 let pos = "imports_of_stream: " in
144 match type_token_of_stream stream
with
146 | Kwd
("var") as ty
->
147 let v = begin match Stream.next stream
with
148 Ident
(s
) -> symbol_of_string s
149 | _
-> failwith
(pos ^
"expected symbol")
154 let prog = { prog with byte_import
= SymbolTable.add
prog.byte_import
v Function
} in
155 imports_of_stream
prog stream
157 let prog = { prog with byte_import
= SymbolTable.add
prog.byte_import
v Variable
} in
158 imports_of_stream
prog stream
159 | _
-> failwith
(pos ^
"expected symbol type")
163 | _
-> failwith
(pos ^
"syntax error")
165 and exports_of_stream
prog stream
=
166 let pos = "imports_of_stream: " in
168 match type_token_of_stream stream
with
170 | Kwd
("var") as ty
->
171 let v = begin match Stream.next stream
with
172 Ident
(s
) -> symbol_of_string s
173 | _
-> failwith
(pos ^
"expected symbol")
178 let prog = { prog with byte_export
= SymbolTable.add
prog.byte_export
v Function
} in
179 exports_of_stream
prog stream
181 let prog = { prog with byte_export
= SymbolTable.add
prog.byte_export
v Variable
} in
182 exports_of_stream
prog stream
183 | _
-> failwith
(pos ^
"expected symbol type")
187 | _
-> failwith
(pos ^
"syntax error")
189 and function_of_stream
prog stream
=
190 let pos = "function_of_stream: " in
192 (* read the name of the function *)
194 begin match Stream.next stream
with
195 Ident
(s
) -> symbol_of_string s
196 | _
-> failwith
(pos ^
"expected function name")
200 (* get the arguments for the function *)
201 let args = arg_list_of_stream
[] stream
in
203 (* get the instructions for the function *)
204 let code = inst_of_stream
[] stream
in
208 block_label
= fun_label;
213 (* add the function to the instruction trace *)
214 let trace = prog.byte_funs
in
215 let fun_list = Trace.to_list
trace in
216 let fun_list = block :: fun_list in
217 { prog with byte_funs
= Trace.of_list
fun_list }
219 and tuple_of_stream
prog stream
=
220 let pos = "tuple_of_stream: " in
222 let tuple_value_of_stream stream
=
223 let pos = pos ^
"tuple_value_of_stream: " in
224 match Stream.next stream
with
225 Kwd
(":") -> Stream.next stream
226 | _
-> failwith
(pos ^
"expected colon (:) operator")
229 let rec tuple_list_of_stream l stream
=
230 let pos = pos ^
"tuple_list_of_stream: " in
232 match Stream.peek stream
with
234 (* create a new tuple data type *)
235 ignore
(Stream.next stream
);
236 let dt = DTTuple
(tuple_list_of_stream [] stream
) in
239 (* there are no more elements in the tuple *)
240 ignore
(Stream.next stream
);
243 (* there are more elements in the tuple *)
244 ignore
(Stream.next stream
);
245 tuple_list_of_stream l stream
247 (* add the element to the tuple *)
248 let ty = type_token_of_stream stream
in
249 let v = tuple_value_of_stream stream
in
250 let dt = data_type_of_token
v ty in
251 tuple_list_of_stream (dt :: l
) stream
254 let addy = addy_of_stream stream
in
256 (* check for the equal sign *)
257 let _ = begin match Stream.next stream
with
259 | _ -> failwith
(pos ^
"expected equal (=) sign")
262 (* check for the open parenthesis; it marks the beginning of the tuple *)
263 let _ = begin match Stream.next stream
with
265 | _ -> failwith
(pos ^
"expected open parenthesis")
268 (* read the data elements of the tuple *)
269 let dt = DTTuple
(tuple_list_of_stream [] stream
) in
270 let v = as_var_of_stream stream
in
273 byte_global
= SymbolTable.add
prog.byte_global
v dt;
274 byte_data
= spset_add
prog.byte_data
v addy dt;
277 and addy_of_stream stream
=
278 let pos = "addy_of_stream: " in
280 let _ = begin match Stream.next stream
with
282 | _ -> failwith
(pos ^
"expected colon (:) operator")
285 let _ = begin match Stream.next stream
with
287 | _ -> failwith
(pos ^
"expected memory ($) operator")
290 match Stream.next stream
with
292 | _ -> failwith
(pos ^
"invalid address")
294 and as_var_of_stream stream
=
295 let pos = "as_var_of_stream: " in
297 match Stream.next stream
with
299 (* read the varaible name *)
300 let next = Stream.next stream
in
301 begin match next with
305 begin match Stream.next stream
with
307 symbol_of_string
("." ^ s
)
308 | _ -> failwith
(pos ^
"expected a variable name")
310 | _ -> failwith
(pos ^
"expected a variable name")
312 | _ -> failwith
(pos ^
"expected the keyword \"as\" operator")
314 and type_token_of_stream stream
=
315 match Stream.next stream
with
316 Kwd
(".") -> Stream.next stream
317 | _ -> failwith
"type_token_of_stream: expected dot (.) operator\n"
319 and value_of_stream stream
=
320 match Stream.next stream
with
321 Kwd
("=") -> Stream.next stream
322 | _ -> failwith
"value_of_stream: expected equal (=) sign"
324 and data_type_of_token
v tok
=
325 let pos = "data_type_of_token: " in
330 Genlex.Char
(c
) -> DTChar
(c
)
331 | _ -> failwith
(pos ^
"expected char value")
335 Genlex.String
(s
) -> DTString
(s
)
336 | _ -> failwith
(pos ^
"expected string value")
340 Genlex.String
(s
) -> DTInt
(Rawint.of_string
Rawint.Int8
true s
)
341 | _ -> failwith
(pos ^
"expected integer value")
345 Genlex.String
(s
) -> DTInt
(Rawint.of_string
Rawint.Int16
true s
)
346 | _ -> failwith
(pos ^
"expected integer value")
350 Genlex.String
(s
) -> DTInt
(Rawint.of_string
Rawint.Int32
true s
)
351 | _ -> failwith
(pos ^
"expected integer value")
355 Genlex.String
(s
) -> DTInt
(Rawint.of_string
Rawint.Int64
true s
)
356 | _ -> failwith
(pos ^
"expected integer value")
360 Genlex.String
(s
) -> DTInt
(Rawint.of_string
Rawint.Int8
false s
)
361 | _ -> failwith
(pos ^
"expected integer value")
365 Genlex.String
(s
) -> DTInt
(Rawint.of_string
Rawint.Int16
false s
)
366 | _ -> failwith
(pos ^
"expected integer value")
370 Genlex.String
(s
) -> DTInt
(Rawint.of_string
Rawint.Int32
false s
)
371 | _ -> failwith
(pos ^
"expected integer value")
375 Genlex.String
(s
) -> DTInt
(Rawint.of_string
Rawint.Int64
false s
)
376 | _ -> failwith
(pos ^
"expected integer value")
380 Genlex.String
(s
) -> DTFloat
(Rawfloat.of_string
Rawfloat.Single s
)
381 | _ -> failwith
(pos ^
"expected floating-point value")
385 Genlex.String
(s
) -> DTFloat
(Rawfloat.of_string
Rawfloat.Double s
)
386 | _ -> failwith
(pos ^
"expected floating-point value")
390 Genlex.String
(s
) -> DTFloat
(Rawfloat.of_string
Rawfloat.LongDouble s
)
391 | _ -> failwith
(pos ^
"expected floating-point value")
393 | _ as data
-> failwith
(pos ^
"undefined data type (" ^
(string_of_token data
) ^
")")
395 and inst_of_stream l stream
=
396 let pos = "inst_of_stream: " in
398 match Stream.next stream
with
432 | Kwd
"xor" as inst
->
433 let l = (binop_inst_of_stream inst stream
) :: l in
434 inst_of_stream
l stream
465 | Kwd
"set" as inst
->
466 let l = (unop_inst_of_stream inst stream
) :: l in
467 inst_of_stream
l stream
471 | Kwd
"native" as inst
->
472 let l = (tailcall_of_stream inst stream
) :: l in
473 inst_of_stream
l stream
475 let l = (extern_of_stream stream
) :: l in
476 inst_of_stream
l stream
478 (* have we reached the end of the function *)
479 begin match Stream.next stream
with
483 failwith
(pos ^
"expected end keyword")
486 failwith
(pos ^
"undefined instruction (" ^
(string_of_token inst
) ^
")")
488 and binop_inst_of_stream inst stream
=
489 let pos = "binop_inst_of_stream: " in
491 let d = operand_of_stream stream
in
493 let s1 = operand_of_stream stream
in
495 let s2 = operand_of_stream stream
in
498 Kwd
"add" -> Add
(d,s1,s2)
499 | Kwd
"sub" -> Sub
(d,s1,s2)
500 | Kwd
"div" -> Div
(d,s1,s2)
501 | Kwd
"mul" -> Mul
(d,s1,s2)
502 | Kwd
"rem" -> Rem
(d,s1,s2)
503 | Kwd
"min" -> Min
(d,s1,s2)
504 | Kwd
"max" -> Max
(d,s1,s2)
505 | Kwd
"f_add" -> FAdd
(d,s1,s2)
506 | Kwd
"f_sub" -> FSub
(d,s1,s2)
507 | Kwd
"f_div" -> FDiv
(d,s1,s2)
508 | Kwd
"f_mul" -> FMul
(d,s1,s2)
509 | Kwd
"f_rem" -> FRem
(d,s1,s2)
510 | Kwd
"f_max" -> FMax
(d,s1,s2)
511 | Kwd
"f_min" -> FMin
(d,s1,s2)
512 | Kwd
"eq" -> Eq
(d,s1,s2)
513 | Kwd
"neq" -> Neq
(d,s1,s2)
514 | Kwd
"gt" -> Gt
(d,s1,s2)
515 | Kwd
"lt" -> Lt
(d,s1,s2)
516 | Kwd
"gte" -> Gte
(d,s1,s2)
517 | Kwd
"lte" -> Lte
(d,s1,s2)
518 | Kwd
"cmp" -> Cmp
(d,s1,s2)
519 | Kwd
"f_eq" -> FEq
(d,s1,s2)
520 | Kwd
"f_neq" -> FNeq
(d,s1,s2)
521 | Kwd
"f_gt" -> FGt
(d,s1,s2)
522 | Kwd
"f_lt" -> FLt
(d,s1,s2)
523 | Kwd
"f_gte" -> FGte
(d,s1,s2)
524 | Kwd
"f_lte" -> FLte
(d,s1,s2)
525 | Kwd
"f_cmp" -> FCmp
(d,s1,s2)
526 | Kwd
"shl" -> Shl
(d,s1,s2)
527 | Kwd
"ashr" -> AShr
(d,s1,s2)
528 | Kwd
"lshr" -> LShr
(d,s1,s2)
529 | Kwd
"and" -> And
(d,s1,s2)
530 | Kwd
"or" -> Or
(d,s1,s2)
531 | Kwd
"xor" -> Xor
(d,s1,s2)
533 failwith
(pos ^
"undefined instruction (" ^
(string_of_token inst
) ^
")")
535 and unop_inst_of_stream inst stream
=
536 let pos = "binop_inst_of_stream: " in
538 let d = operand_of_stream stream
in
540 let s = operand_of_stream stream
in
543 Kwd
"not" -> Not
(d,s)
544 | Kwd
"uminus" -> UMinus
(d,s)
545 | Kwd
"abs" -> Abs
(d,s)
546 | Kwd
"f_uminus" -> FUMinus
(d,s)
547 | Kwd
"f_abs" -> FAbs
(d,s)
548 | Kwd
"sin" -> Sin
(d,s)
549 | Kwd
"cos" -> Cos
(d,s)
550 | Kwd
"sqrt" -> Sqrt
(d,s)
551 | Kwd
"f_2_uint8" -> FToUInt8
(d,s)
552 | Kwd
"f_2_uint16" -> FToUInt16
(d,s)
553 | Kwd
"f_2_uint32" -> FToUInt32
(d,s)
554 | Kwd
"f_2_uint64" -> FToUInt64
(d,s)
555 | Kwd
"f_2_int8" -> FToInt8
(d,s)
556 | Kwd
"f_2_int16" -> FToInt16
(d,s)
557 | Kwd
"f_2_int32" -> FToInt32
(d,s)
558 | Kwd
"f_2_int64" -> FToInt64
(d,s)
559 | Kwd
"f_2_float32" -> FToFloat32
(d,s)
560 | Kwd
"f_2_floot64" -> FToFloat64
(d,s)
561 | Kwd
"f_2_float80" -> FToFloat80
(d,s)
562 | Kwd
"i_2_float32" -> IToFloat32
(d,s)
563 | Kwd
"i_2_float64" -> IToFloat64
(d,s)
564 | Kwd
"i_2_float80" -> IToFloat80
(d,s)
565 | Kwd
"i_2_int8" -> IToInt8
(d,s)
566 | Kwd
"i_2_int16" -> IToInt16
(d,s)
567 | Kwd
"i_2_int32" -> IToInt32
(d,s)
568 | Kwd
"i_2_int64" -> IToInt64
(d,s)
569 | Kwd
"i_2_uint8" -> IToUInt8
(d,s)
570 | Kwd
"i_2_uint16" -> IToUInt16
(d,s)
571 | Kwd
"i_2_uint32" -> IToUInt32
(d,s)
572 | Kwd
"i_2_uint64" -> IToUInt64
(d,s)
573 | Kwd
"set" -> Set
(d,s)
575 failwith
(pos ^
"undefined instruction (" ^
(string_of_token inst
) ^
")")
577 and tailcall_of_stream inst stream
=
578 let pos = "tailcall_of_stream: " in
580 let v = operand_of_stream stream
in
581 let args = arg_list_of_stream
[] stream
in
584 Kwd
"goto" -> Goto
(v,args)
585 | Kwd
"call" -> Call
(v,args)
586 | Kwd
"callex" -> CallEx
(v,args)
587 | Kwd
"native" -> Native
(v,args)
589 failwith
(pos ^
"undefined instruction (" ^
(string_of_token inst
) ^
")")
591 and extern_of_stream stream
=
592 let pos = "extern_of_stream: " in
594 let v = operand_of_stream stream
in
596 begin match Stream.next stream
with
598 | _ -> failwith
(pos ^
"expected function name")
602 let args = arg_list_of_stream
[] stream
in
605 and arg_list_of_stream
l stream
=
606 let pos = "arg_list_of_stream: " in
608 match Stream.next stream
with
610 (* begin a new argument list *)
611 let l = [(operand_of_stream stream
)] in
612 arg_list_of_stream
l stream
614 (* read the next argument *)
615 let l = (operand_of_stream stream
) :: l in
616 arg_list_of_stream
l stream
618 (* end of the argument list *)
621 failwith
(pos ^
"syntax error")
623 and operand_of_stream stream
=
624 let pos = "operand_of_stream: " in
626 match Stream.next stream
with
628 Var
(symbol_of_string
s)
630 begin match Stream.next stream
with
631 | Genlex.Int
(i
) -> Memory
(i
)
632 | _ -> failwith
(pos ^
"expected memory address")
634 | _ as op
-> failwith
(pos ^
"illegal operand (" ^
(string_of_token op
) ^
")")
636 and skip_comma stream
=
637 match Stream.peek stream
with
638 Some
(Kwd
",") -> ignore
(Stream.next stream
)
639 | _ -> failwith
"expected comma operator"
645 * This function is used with printing errors messages to the
646 * screen. It returns a string representing the value of the
649 and string_of_token
= function
651 | Genlex.Ident
(s) -> s
652 | Genlex.Int
(i
) -> string_of_int i
653 | Genlex.Float
(f
) -> string_of_float f
654 | Genlex.String
(s) -> s
655 | Genlex.Char
(c
) -> String.make
1 c
657 (**********************************************************************
660 let prog_of_file in_filename
=
662 byte_import
= SymbolTable.empty
;
663 byte_export
= SymbolTable.empty
;
664 byte_global
= SymbolTable.empty
;
666 byte_data
= spset_empty
();
669 (* open the output file and transform it into tokens *)
670 let in_file = open_in in_filename
in
671 let token_stream = lexer (Stream.of_channel
in_file) in
672 (* close_in in_file; *)
674 (* parse the tokens to create a 'prog' *)
675 let prog = prog_of_stream prog token_stream in
679 (* see what happened *)
680 Byte_print.print_prog
Format.std_formatter
prog;
682 (* end see what happend *)