-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
OCaml backend #148
Draft
mdurero
wants to merge
55
commits into
master
Choose a base branch
from
backend-ocaml
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
OCaml backend #148
Changes from all commits
Commits
Show all changes
55 commits
Select commit
Hold shift + click to select a range
6b00947
Report work on parser from ocaml-backend branch
mdurero 68ea878
Reinstate old empty fields, if by chance some files from 2019 must be…
mdurero 3d3aec5
Describe tokens in comments
mdurero 1ee211b
OCaml backend start
mdurero 2f0249b
Add header defining M types and variables tables.
mdurero 9e8e284
Define a M rule as an OCaml function of a list of M values.
mdurero 57da532
Generate local and tgv variable assignment as OCaml array set.
mdurero 03d69dd
Ignore VSCodium config files
mdurero f23f126
Formatting
mdurero f232d1e
Adjust to pull request #146 generic-table-access
mdurero 5169712
Add empty expression at the end of each generated rule
mdurero 24e84f5
New makefile target : compiling result to native code.
mdurero 9d92f76
Generate OCaml functions corresponding to M binary and unary operators
mdurero bf306c5
Define M types and operators in a static OCaml library.
mdurero 6a8b168
Cleaning
mdurero a852bab
Add M functions to the OCaml library and use them in generated code
mdurero ace22fb
More thorough cleaning
mdurero d2dfcc7
Generate Mpp condition, rule and function calls.
mdurero 58fb9df
Enable debug symbols on bytecode target
mdurero 6482ec8
Fix Mpp condition generation
mdurero 7daae5e
Formatting
mdurero 1047796
Input handling OCaml backend
mdurero 768b8cd
Adjust OCaml backend to pull request #153 mpp function data structure
mdurero 84e2fae
Add output to the sort of main function calculate_tax
mdurero 6552368
WIP test harness: load FIP files, call the compiled result of OCaml b…
mdurero 4bb21bc
Fix m_neg function: output of defined M value should be defined
mdurero 5f799af
Write discrepancies between FIP file and computation result as a test…
mdurero 316f477
Fix m_round: use ceil for negative values.
mdurero 032bae4
Fix Mpp conditional: true and false expressions were inverted
mdurero 428ccf1
Test harness for OCaml backend: can print discrepancy reports for a s…
mdurero f00f9f2
Fix: if bool then true else false
mdurero 69cd84f
Add warning when a FIP file expects an output variable which is not i…
mdurero c2bf05a
Add a test command to write raw inputs and outputs of a FIP test
mdurero 69e21bb
M errors and verifications are now recorded and an output of the main…
mdurero 5fdb8f5
Refactor Makefile: allow to disable m_spec file usage, to select .m_s…
mdurero 2f05d7d
Adjust OCaml backend to pull request #158 as M verifs are now process…
mdurero ccab1f6
M Errors of type Anomaly now abort computation raising an M Exception…
mdurero e06888d
Fix blank lines in the input map building
mdurero 2a840bb
Ouput of main function is now an array, not a list. Fix multiple conc…
mdurero 4f3c39a
Fix min, max & multimax having always defined result, following chang…
mdurero 1f0e4a0
Adapt to Bir changes in PR #184
mdurero 48135ad
Fix stack overflow by building static input and output arrays of the …
mdurero d2a1707
Add a crude independant OCaml test file parser by cherry-picking rele…
mdurero e4845d8
Plug the new parser in place of the old ad hoc file loading with patt…
mdurero 498da98
Remove ad hoc function for test file loading witch pattern matching
mdurero 8eb89d8
Compatibility change for Ocaml compiler 4.11.2
mdurero 894aa86
Add a run_tests build command without file output for CI
mdurero 0cd326b
Refactor Makefiles for Ocaml backend and parser to improve readabilit…
mdurero 291a857
Enable Ocaml backend check in continuous integration
mdurero 9e4e70b
Fix guarding condition to avoid reading out of bound values in access…
mdurero 04cbf67
Refactor static OCaml multimax to use Array module function properly
mdurero bf10615
Add abs function to OCaml backend, following aa702f2a (rehabilitate a…
mdurero d09444b
Use the new access to variable definition from Bir, from PR #200
mdurero cd23ed2
Refine an independent IRJ test files parser. Compatibility with both …
mdurero ebfa4e3
Add a future dune file for Ocaml backend. Commented as work on the pa…
mdurero File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,3 +6,5 @@ doc.html | |
*~ | ||
/_opam | ||
/Makefile.config | ||
/.vscode | ||
examples/ocaml/**/.merlin |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
include Makefile-generic-ocaml-rules.include | ||
include ../../Makefile.include | ||
|
||
######## | ||
# USAGE: specifiying parameters of the generated "calculette" | ||
######## | ||
# Specifying a mpp file and its main function: | ||
# make ir.ml MPP_FILE=../../mpp_specs/dgfip_base.mpp MPP_FUNCTION=verif_calcul_primitive_raw | ||
# Using the default m_spec file: | ||
# make ir.ml TAKE_MSPEC=true | ||
|
||
MLANG_BIN=dune exec --no-print-director ../../src/main.exe -- | ||
MPP_FUNCTION=compute_double_liquidation_pvro | ||
M_SPEC_FILE=$(SELF_DIR)/m_specs/tests_$(YEAR).m_spec | ||
|
||
MLANG_DEFAULT_OPTS=\ | ||
--display_time --debug \ | ||
--mpp_file=$(MPP_FILE) \ | ||
--mpp_function=$(MPP_FUNCTION) | ||
|
||
MLANG_MSPEC=\ | ||
--function_spec=$(M_SPEC_FILE) | ||
|
||
ifdef TAKE_MSPEC | ||
MLANG=$(MLANG_BIN) $(MLANG_DEFAULT_OPTS) $(OPTIMIZE_FLAG) $(MLANG_MSPEC) | ||
SPEC_DEP=$(MPP_FILE) $(M_SPEC_FILE) | ||
else | ||
MLANG=$(MLANG_BIN) $(MLANG_DEFAULT_OPTS) $(OPTIMIZE_FLAG) | ||
SPEC_DEP=$(MPP_FILE) | ||
endif | ||
|
||
# Include parser lib directory to make its module available | ||
OCAMLC_INCLUDE_LIST= -I parser | ||
|
||
.PHONY : clean cleangen cleancalc cleanstat cleantest cleanresult run_tests | ||
|
||
clean: cleancalc cleanstat cleanresult cleanparser | ||
|
||
cleangen: | ||
rm -f ir.ml | ||
cleancalc: cleangen | ||
rm -f ir.cmi ir.cmx ir.o ir.cmo ir.exe ir.bc | ||
cleantest: | ||
rm -f test_harness.cmi test_harness.cmx test_harness.o test_harness.cmo test.exe test.bc | ||
cleanstat: cleantest | ||
rm -f mvalue.cmi mvalue.cmx mvalue.o mvalue.cmo | ||
cleanresult: | ||
rm -f results/* | ||
cleanparser: | ||
$(MAKE) -C parser/ clean | ||
|
||
################################################## | ||
# Generating and running OCaml files from Mlang | ||
################################################## | ||
|
||
# Generating OCaml files (MLang) | ||
ir.ml: $(SPEC_DEP) | ||
$(MLANG) \ | ||
--backend ocaml --output ir.ml \ | ||
$(SOURCE_FILES) | ||
|
||
.INTERMEDIATE : test_harness.cmo test_harness.cmi test_harness.o test_harness.cmx | ||
# Compiling bytecode | ||
types_module.cmo test_lexer.cmo test_parser.cmo fip.cmo: | ||
$(MAKE) -C parser/ fip.cmo | ||
|
||
test.bc: types_module.cmo test_lexer.cmo test_parser.cmo fip.cmo mvalue.cmo ir.cmo test_harness.cmo | ||
ocamlc.opt $(DEBUG_FLAG) -o $@ $(OCAMLC_INCLUDE_LIST) unix.cma $^ | ||
|
||
# Compiling native code | ||
types_module.cmx test_lexer.cmx test_parser.cmx fip.cmx: | ||
$(MAKE) -C parser/ fip.cmx | ||
|
||
test.exe: types_module.cmx test_lexer.cmx test_parser.cmx fip.cmx mvalue.cmx ir.cmx test_harness.cmx | ||
ocamlopt $(DEBUG_FLAG) -o $@ $(OCAMLC_INCLUDE_LIST) unix.cmxa $^ | ||
|
||
# Running test suite | ||
run: test.bc | ||
./test.bc "multi" $(TESTS_DIR) "results/y_$(YEAR)" | ||
|
||
runfile: test.bc | ||
./test.bc "raw" $(FILE) "results/f_$(notdir $(FILE))" | ||
|
||
runx: test.exe | ||
./test.exe "multi" $(TESTS_DIR) "results/y_$(YEAR)" | ||
|
||
# run_tests uses an empty string to disable the file output (output is enabled on stdout). | ||
run_tests: test.exe | ||
./test.exe "multi" $(TESTS_DIR) "" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
################################################## | ||
# Implicit rules for OCaml modules | ||
################################################## | ||
|
||
%.cmi: %.mli | ||
ocamlc.opt -c $(DEBUG_FLAG) $^ | ||
|
||
%.cmo: %.ml | ||
ocamlc.opt -c $(DEBUG_FLAG) $(OCAMLC_INCLUDE_LIST) $^ | ||
|
||
%.cmx: %.ml | ||
ocamlopt -c $(DEBUG_FLAG) $(OCAMLC_INCLUDE_LIST) $^ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
;(executable | ||
; (name test_harness) | ||
; (libraries mlang)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
type m_value = { undefined : bool; value : float } | ||
|
||
type m_array = m_value array | ||
|
||
type m_error = { | ||
name : string; | ||
kind : string; | ||
major_code : string; | ||
minor_code : string; | ||
description : string; | ||
alias : string; | ||
} | ||
|
||
exception M_exn of m_error list | ||
|
||
type m_context = { | ||
tgv : m_array; | ||
local_variables : m_array; | ||
mutable errors : m_error list; | ||
} | ||
|
||
type revenue_code = { alias : string; value : float } | ||
|
||
module TgvPositionMap = Map.Make (String) | ||
|
||
type input_list = revenue_code list | ||
|
||
type output_array = revenue_code array | ||
|
||
let m_undef : m_value = { undefined = true; value = 0.0 } | ||
|
||
let m_zero : m_value = { undefined = false; value = 0.0 } | ||
|
||
let m_one : m_value = { undefined = false; value = 1.0 } | ||
|
||
let m_add (x : m_value) (y : m_value) : m_value = | ||
if x.undefined && y.undefined then m_undef | ||
else { undefined = false; value = x.value +. y.value } | ||
|
||
let m_multiply (x : m_value) (y : m_value) : m_value = | ||
if x.undefined || y.undefined then m_undef | ||
else { undefined = false; value = x.value *. y.value } | ||
|
||
let m_subtract (x : m_value) (y : m_value) : m_value = | ||
if x.undefined && y.undefined then m_undef | ||
else { undefined = false; value = x.value -. y.value } | ||
|
||
let m_divide (x : m_value) (y : m_value) : m_value = | ||
if x.undefined || y.undefined then m_undef | ||
else | ||
{ | ||
undefined = false; | ||
value = (if y.value = 0.0 then 0.0 else x.value /. y.value); | ||
} | ||
|
||
let m_and (x : m_value) (y : m_value) : m_value = | ||
if x.undefined || y.undefined then m_undef | ||
else if x.value <> 0.0 && y.value <> 0.0 then m_one | ||
else m_zero | ||
|
||
let m_or (x : m_value) (y : m_value) : m_value = | ||
if x.undefined && y.undefined then m_undef | ||
else if x.value <> 0.0 || y.value <> 0.0 then m_one | ||
else m_zero | ||
|
||
let m_cond (condition : m_value) (true_value : m_value) (false_value : m_value) | ||
: m_value = | ||
match condition with | ||
| { undefined = true; value = _ } -> m_undef | ||
| { undefined = false; value = 0.0 } -> false_value | ||
| { undefined = false; value = _ } -> true_value | ||
|
||
let m_greater_than (x : m_value) (y : m_value) : m_value = | ||
if x.undefined || y.undefined then m_undef | ||
else if x.value > y.value then m_one | ||
else m_zero | ||
|
||
let m_greater_than_equal (x : m_value) (y : m_value) : m_value = | ||
if x.undefined || y.undefined then m_undef | ||
else if x.value >= y.value then m_one | ||
else m_zero | ||
|
||
let m_less_than (x : m_value) (y : m_value) : m_value = | ||
if x.undefined || y.undefined then m_undef | ||
else if x.value < y.value then m_one | ||
else m_zero | ||
|
||
let m_less_than_equal (x : m_value) (y : m_value) : m_value = | ||
if x.undefined || y.undefined then m_undef | ||
else if x.value <= y.value then m_one | ||
else m_zero | ||
|
||
let m_equal (x : m_value) (y : m_value) : m_value = | ||
if x.undefined || y.undefined then m_undef | ||
else if x.value = y.value then m_one | ||
else m_zero | ||
|
||
let m_not_equal (x : m_value) (y : m_value) : m_value = | ||
if x.undefined || y.undefined then m_undef | ||
else if x.value <> y.value then m_one | ||
else m_zero | ||
|
||
let m_not (x : m_value) : m_value = | ||
if x.undefined then m_undef else if x.value = 0.0 then m_one else m_zero | ||
|
||
let m_neg (x : m_value) : m_value = | ||
if x.undefined then m_undef | ||
else { undefined = false; value = Float.neg x.value } | ||
|
||
let m_table_value_at_index (variable_array : m_array) (table_start : int) | ||
(index : m_value) (size : int) = | ||
if index.undefined then m_undef | ||
else | ||
let offset = int_of_float index.value in | ||
match offset with | ||
| x when x < 0 -> m_zero | ||
| x when x >= size -> m_undef | ||
| _ -> Array.get variable_array (offset + table_start) | ||
|
||
let m_max (x : m_value) (y : m_value) : m_value = | ||
if x.undefined && y.undefined then m_undef | ||
else { undefined = false; value = max x.value y.value } | ||
|
||
let m_min (x : m_value) (y : m_value) : m_value = | ||
if x.undefined && y.undefined then m_undef | ||
else { undefined = false; value = min x.value y.value } | ||
|
||
let m_round (x : m_value) : m_value = | ||
if x.undefined then m_undef | ||
else | ||
{ | ||
undefined = false; | ||
value = | ||
(if x.value < 0.0 then ceil (x.value -. 0.50005) | ||
else floor (x.value +. 0.50005)); | ||
} | ||
|
||
let m_null = m_not | ||
|
||
let m_floor (x : m_value) : m_value = | ||
if x.undefined then m_undef | ||
else { undefined = false; value = floor (x.value +. 0.000001) } | ||
|
||
let m_abs (x : m_value) : m_value = | ||
if x.undefined then m_undef | ||
else { undefined = false; value = abs_float x.value } | ||
|
||
let m_present (x : m_value) : m_value = if x.undefined then m_zero else m_one | ||
|
||
let m_multimax (bound_variable : m_value) (variable_array : m_array) | ||
(position : int) : m_value = | ||
if bound_variable.undefined then failwith "Multimax bound undefined!" | ||
else | ||
let bound = int_of_float bound_variable.value in | ||
let sub_array = Array.sub variable_array (position+1) (bound) in | ||
let get_position_value position = | ||
Array.get variable_array position | ||
in | ||
Array.fold_left (m_max) (get_position_value position) sub_array |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
include ../Makefile-generic-ocaml-rules.include | ||
|
||
clean: | ||
rm -f *.cmo *.cmi *.cmx *.o test_lexer.ml test_parser.ml test_parser.mli | ||
|
||
# Compiling test file parser | ||
|
||
test_parser.mli test_parser.ml: types_module.cmo types_module.cmx | ||
menhir --infer-write-query mock.ml test_parser.mly | ||
ocamlc.opt -i mock.ml > reply | ||
menhir --infer-read-reply reply test_parser.mly | ||
rm mock.ml reply | ||
|
||
test_lexer.ml: test_parser.cmi test_parser.cmo test_parser.cmx | ||
ocamllex test_lexer.mll | ||
|
||
fip.cmo: test_lexer.cmo | ||
|
||
fip.cmx: test_lexer.cmx |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
(*From test_interpreter.ml*) | ||
|
||
open Types_module | ||
|
||
let parse_file (test_name : string) : Types_module.irj_file = | ||
let input = open_in test_name in | ||
let filebuf = Lexing.from_channel input in | ||
let filebuf = | ||
{ | ||
filebuf with | ||
lex_curr_p = { filebuf.lex_curr_p with pos_fname = test_name }; | ||
} | ||
in | ||
let f = | ||
try Test_parser.irj_file Test_lexer.token filebuf with | ||
| Types_module.StructuredError e -> | ||
close_in input; | ||
raise (Types_module.StructuredError e) | ||
| Test_parser.Error -> | ||
close_in input; | ||
Types_module.raise_spanned_error "Test syntax error" | ||
(Types_module.mk_position (filebuf.lex_start_p, filebuf.lex_curr_p)) | ||
in | ||
close_in input; | ||
f | ||
(* | ||
let () = | ||
let donnees = parse_file "alavoine-2.irj" in | ||
let (entrees, _, _) = donnees.prim in | ||
print_string donnees.nom;print_newline(); | ||
let (code, valeur, _) = List.hd entrees in | ||
print_string "première entrée : "; print_string code; print_string " avec la valeur "; | ||
match valeur with | ||
| I entier -> print_int entier; print_string " entière.";print_newline();flush stdout | ||
| F flottant -> print_float flottant; print_string " flottante."; | ||
print_newline(); | ||
flush stdout | ||
*) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Habile