From 6a51194f90ed664e51f5a7bf1bbb804ffacb3aa8 Mon Sep 17 00:00:00 2001 From: joao Date: Wed, 9 Nov 2022 18:26:49 -0300 Subject: [PATCH] stable ready for release --- .dockerignore | 3 +- .gitignore | 1 + Makefile | 42 ++++++++++++------------- devtools/Dockerfile | 17 +++++----- devtools/bootstrap.sh | 8 +++-- libs/shell/__init__.fy | 5 ++- pretty_error2.py | 12 +++---- src/core/generator/Conversor.fy | 16 ---------- src/core/parser/__init__.fy | 28 ++++++++++++++--- src/core/parser/functions.fy | 8 ++--- src/core/parser/pos/localcalls.fy | 52 ++++++++++++++++--------------- 11 files changed, 100 insertions(+), 92 deletions(-) diff --git a/.dockerignore b/.dockerignore index cbf7b8b..606fc62 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,4 +1,5 @@ **/_compiled/ /bin/ /Makefile -**/erl_crash.dump \ No newline at end of file +**/erl_crash.dump +bootstraped \ No newline at end of file diff --git a/.gitignore b/.gitignore index d3bde1b..b97976d 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ src/_compiled /example/ **/erl_crash.dump libs/fy_doc/_env +bootstraped diff --git a/Makefile b/Makefile index 1f4a149..55724d9 100644 --- a/Makefile +++ b/Makefile @@ -12,44 +12,44 @@ SHELL_DOCKER_TAG:="fython:shell" FYTEST_DOCKER_TAG:="fython:fytest" TESTS_DOCKER_TAG:="fython:tests" - +.ONESHELL: bootstrap-with-docker: - DOCKER_BUILDKIT=1 docker build -f devtools/Dockerfile -t $(BOOTSTRAP_DOCKER_TAG) --target bootstrap . || exit 1 + DOCKER_BUILDKIT=1 docker build -f devtools/Dockerfile -t $(BOOTSTRAP_DOCKER_TAG) --target bootstrap . \ + && docker rm -f fython_bootstrap || true \ + && docker run \ + --name fython_bootstrap \ + -v $(ROOT_DIR)/bootstraped:/final_bootstrap \ + -e FINAL_PATH='/final_bootstrap' \ + $(BOOTSTRAP_DOCKER_TAG) && echo "Bootstrap finished. Result saved at '$(ROOT_DIR)/bootstraped'" -.ONESHELL: compile-project: # USAGE: # > make compile-project path=/home/joao/fython/example - DOCKER_BUILDKIT=1 docker build -f devtools/Dockerfile -t $(COMPILER_DOCKER_TAG) --target compiler . || exit 1 - DOCKER_BUILDKIT=1 docker run --env PROJET_FOLDER=/project$(path) -v $(path):/project$(path) $(COMPILER_DOCKER_TAG) || exit 1 + DOCKER_BUILDKIT=1 docker build -f devtools/Dockerfile -t $(COMPILER_DOCKER_TAG) --target compiler . \ + && DOCKER_BUILDKIT=1 docker run --env PROJET_FOLDER=/project$(path) -v $(path):/project$(path) $(COMPILER_DOCKER_TAG) -.ONESHELL: run-tests: # > make run-tests - $(MAKE) build-fytest - DOCKER_BUILDKIT=1 docker run -e FOLDER=$(TESTS_PATH) -v $(TESTS_PATH):$(TESTS_PATH) $(FYTEST_DOCKER_TAG) || exit 1 + $(MAKE) build-fytest \ + && DOCKER_BUILDKIT=1 docker run -e FOLDER=$(TESTS_PATH) -v $(TESTS_PATH):$(TESTS_PATH) $(FYTEST_DOCKER_TAG) -.ONESHELL: build-shell: - DOCKER_BUILDKIT=1 docker build -f devtools/Dockerfile -t $(SHELL_DOCKER_TAG) --target shell . || exit 1 + DOCKER_BUILDKIT=1 docker build -f devtools/Dockerfile -t $(SHELL_DOCKER_TAG) --target shell . -.ONESHELL: build-fytest: - DOCKER_BUILDKIT=1 docker build -f devtools/Dockerfile -t $(FYTEST_DOCKER_TAG) --target fytest . || exit 1 + DOCKER_BUILDKIT=1 docker build -f devtools/Dockerfile -t $(FYTEST_DOCKER_TAG) --target fytest . -.ONESHELL: shell-current-src: - $(MAKE) build-shell - DOCKER_BUILDKIT=1 docker run -it $(SHELL_DOCKER_TAG) || exit 1 + $(MAKE) build-shell \ + && DOCKER_BUILDKIT=1 docker run -it $(SHELL_DOCKER_TAG) -.ONESHELL: project-shell: # > project-shell path=/home/joao/fython/example - $(MAKE) compile-project path=$(path) - $(MAKE) build-shell - DOCKER_BUILDKIT=1 docker run -it --env ADITIONAL_PATHS=/project$(path)/_compiled -v $(path):/project$(path) $(SHELL_DOCKER_TAG) || exit 1 + $(MAKE) compile-project path=$(path) \ + && $(MAKE) build-shell\ + && DOCKER_BUILDKIT=1 docker run -it --env ADITIONAL_PATHS=/project$(path)/_compiled -v $(path):/project$(path) $(SHELL_DOCKER_TAG) project-bash: # > project-bash path=/home/joao/fython/example - $(MAKE) compile-project path=$(path) - DOCKER_BUILDKIT=1 docker run -it --env ADITIONAL_PATHS=/project$(path)/_compiled -v $(path):/project$(path) $(SHELL_DOCKER_TAG) bash || exit 1 + $(MAKE) compile-project path=$(path) \ + && DOCKER_BUILDKIT=1 docker run -it --env ADITIONAL_PATHS=/project$(path)/_compiled -v $(path):/project$(path) $(SHELL_DOCKER_TAG) bash diff --git a/devtools/Dockerfile b/devtools/Dockerfile index 0fd71c4..115680c 100644 --- a/devtools/Dockerfile +++ b/devtools/Dockerfile @@ -31,9 +31,16 @@ RUN echo "Bootstraping using Fython $VERSION_TO_USE_AS_BOOTSTRAPER" \ RUN rm -rf $PATH_FYTHON_TO_USE_AS_BOOTSTRAPER FROM base as bootstrap +ENV FIRST_PATH="/test_compiled1" +ENV SECOND_PATH="/test_compiled2" + # Check if it can recompile itself (its a good way to test while we dont have proper testing) -RUN ./bootstrap.sh compile /src /test_compiled1 $DESTINE_PATH $ELIXIR_BEAMS_PATH -RUN ./bootstrap.sh compile /src /test_compiled2 /test_compiled1 +RUN ./bootstrap.sh compile /src $FIRST_PATH $DESTINE_PATH $ELIXIR_BEAMS_PATH +RUN ./bootstrap.sh compile /src $SECOND_PATH $FIRST_PATH $ELIXIR_BEAMS_PATH + +# The final version bootstraped ready for release +ENV FINAL_PATH="/bootstraped" +CMD ./bootstrap.sh compile /src $FINAL_PATH $SECOND_PATH $ELIXIR_BEAMS_PATH FROM base as shell ENV ADITIONAL_PATHS="" @@ -51,12 +58,6 @@ CMD echo "Compiling project: $PROJET_FOLDER" \ && rm -rf $PROJET_FOLDER/_compiled \ && /fython exec "Core.Code.compile_project('$PROJET_FOLDER')" $DESTINE_PATH -FROM base as tests -COPY tests tests - -CMD /fython exec "Core.Code.compile_project('/tests')" $DESTINE_PATH \ - && /fython exec "Tests.Math_tests.run_tests()" $DESTINE_PATH /tests/_compiled - FROM base as fytest ENV FOLDER="MUST_BE_GIVEN" diff --git a/devtools/bootstrap.sh b/devtools/bootstrap.sh index e125518..bd858dd 100755 --- a/devtools/bootstrap.sh +++ b/devtools/bootstrap.sh @@ -10,11 +10,15 @@ compile () { ELIXIR_BEAMS_PATH_COMP=$4 COMPILE_IN_PARALEL=true + [[ -z "$SRC_DIR_COMP" ]] && echo "Missing src dir of fython" && exit 1 + [[ -z "$DESTINE_PATH_COMP" ]] && echo "Missing destine path of bootstrap" && exit 1 + [[ -z "$PATH_FYTHON_TO_USE_AS_BOOTSTRAPER_COMP" ]] && echo "Missing path of previous fython to use as bootstraper" && exit 1 + [[ -z "$ELIXIR_BEAMS_PATH_COMP" ]] && echo "Missing elixir beams path" && exit 1 + ALL_FILES_PATH_COMP=$(find $SRC_DIR_COMP -name '*.fy') echo "Destine folder: $DESTINE_PATH_COMP" - rm -rf $DESTINE_PATH_COMP - mkdir $DESTINE_PATH_COMP + rm -rf $DESTINE_PATH_COMP/* cd $ELIXIR_BEAMS_PATH_COMP && cp -r . "$DESTINE_PATH_COMP" && cd / diff --git a/libs/shell/__init__.fy b/libs/shell/__init__.fy index 5c9970d..0688e92 100644 --- a/libs/shell/__init__.fy +++ b/libs/shell/__init__.fy @@ -84,7 +84,10 @@ def execute(text, env, config): try: config = Elixir.Map.put(config, 'env', env) (result, new_env) = Core.eval_string('', text, config) - Elixir.IO.inspect(result) + case result: + None -> None + _ -> Elixir.IO.inspect(result) + (result, new_env) except error: # usefull for debuggind diff --git a/pretty_error2.py b/pretty_error2.py index 4db2704..ade6256 100644 --- a/pretty_error2.py +++ b/pretty_error2.py @@ -26,7 +26,7 @@ def da_erro(a): def get_lines_above(state): - HOW_MANY_LINES_SHOW_ABOVE = 3 + HOW_MANY_LINES_SHOW_ABOVE = 5 source_code_lines = [(num, line) for num, line in enumerate(state['source_code_lines'])] @@ -42,16 +42,12 @@ def draw_pointers(state): start, end = state['start'][1], state['end'][1] pointer = " " * (get_need_size_numbers(state) + 3) - below = "" for i in range(0, start): - pointer += ' ' - below += "=" + pointer += '~' for i in range(start, end): pointer += "^" - below += "=" - - return [pointer + " erro aconteceu aq", below] + return [pointer] def get_lines_to_print(state): @@ -73,7 +69,7 @@ def get_need_size_numbers(state): def add_line_numbers(meta, list_of_lines_indexed): size = get_need_size_numbers(meta) return [ - f"{str(i + 1).rjust(size)} | {l}" for i, l in list_of_lines_indexed + f"{str(i + 1).rjust(size)} ǁ {l}" for i, l in list_of_lines_indexed ] diff --git a/src/core/generator/Conversor.fy b/src/core/generator/Conversor.fy index 9fb8952..1070bcb 100644 --- a/src/core/generator/Conversor.fy +++ b/src/core/generator/Conversor.fy @@ -59,11 +59,6 @@ def convert_var((:var, meta, [False, value])): (Elixir.String.to_atom(value), meta, :Elixir) def convert_string((:string, meta, [value])): - # TODO eval??, temos q rever o scaping -# Elixir.IO.inspect('convertendooo') -# Elixir.IO.inspect(value) -# value = Elixir.Enum.join(['"', value,'"']) |> Elixir.Code.eval_string() |> Elixir.Kernel.elem(0) -# (:"<<>>", meta, [value]) value def convert_unary((:unary, meta, [:minus, node])): @@ -372,17 +367,6 @@ def convert_try((:try, meta, [try_block, exceptions, finally_block])): convert(block) ] ) - (False, None) -> - # Case of: - # > except ArithmeticError: - ( - :"->", - meta, - [ - [(:'__aliases__', [(:alias, False)], [Elixir.String.to_atom(except_identifier)])], - convert(block) - ] - ) (True, _) -> # Case of: # > except ArithmeticError as error: diff --git a/src/core/parser/__init__.fy b/src/core/parser/__init__.fy index 37556bb..7f1970d 100644 --- a/src/core/parser/__init__.fy +++ b/src/core/parser/__init__.fy @@ -677,7 +677,7 @@ def case_expr(state): is_cond = (state["current_tok"]["type"]) == "DO" - [state, _expr] = case is_cond: + [state, case_expr] = case is_cond: True -> [state, None] False -> expr(state) @@ -716,8 +716,25 @@ def case_expr(state): [state, left_expr] = expr(state) - case (state['current_tok']['type']) == 'ARROW': - True -> + state = case [case_expr, left_expr]: + [None, (:var, _, [_, "_"])] -> + Core.Parser.Utils.set_error( + state, + "If you want a clause to always match, you should use: True", + state["prev_tok"]["pos_start"], + state["prev_tok"]["pos_start"], + ) + [None, (:var, _, [_, "False"])] -> + Core.Parser.Utils.set_error( + state, + "False is not allowed here as it will never matchs", + state["prev_tok"]["pos_start"], + state["prev_tok"]["pos_end"], + ) + _ -> state + + case [state['error'],(state['current_tok']['type']) == 'ARROW']: + [None, True] -> state = advance(state) [state, right_expr] = case (state['current_tok']['ident']) == this_ident: @@ -727,13 +744,14 @@ def case_expr(state): cases = [*cases, (left_expr, right_expr)] state |> Elixir.Map.put('_cases', cases) - False -> + [None, False] -> Core.Parser.Utils.set_error( state, "Expected '->'", state["current_tok"]["pos_start"], state["current_tok"]["pos_end"] ) + [_, _] -> state ) False -> Core.Parser.Utils.set_error( @@ -758,7 +776,7 @@ def case_expr(state): state = Elixir.Map.delete(state, '_cases') node = Core.Parser.Nodes.make_case_node( - state['file'], _expr, cases, pos_start, state['current_tok']['pos_start'] + state['file'], case_expr, cases, pos_start, state['current_tok']['pos_start'] ) [state, node] diff --git a/src/core/parser/functions.fy b/src/core/parser/functions.fy index 986886f..ec4d504 100644 --- a/src/core/parser/functions.fy +++ b/src/core/parser/functions.fy @@ -48,9 +48,9 @@ def func_def_expr(state): True -> advance(state) False -> Core.Parser.Utils.set_error( state, - "Expected ':'", - state["current_tok"]["pos_start"], - state["current_tok"]["pos_end"] + "Missing ':' after function definition", + state["prev_tok"]["pos_end"], + state["prev_tok"]["pos_end"] ) state = case (state['current_tok']['pos_start']['ln']) > def_token_ln: @@ -79,7 +79,6 @@ def func_def_expr(state): case [arg_nodes, body]: [_, None] -> [state, None] [None, _] -> [state, None] - [None, None] -> [state, None] _ -> node = Core.Parser.Nodes.make_funcdef_node( state['file'], var_name_tok, arg_nodes, body, docstring, pos_start @@ -113,7 +112,6 @@ def lambda_expr(state): case [arg_nodes, body]: [_, None] -> [state, None] [None, _] -> [state, None] - [None, None] -> [state, None] _ -> node = Core.Parser.Nodes.make_lambda_node( state['file'], None, arg_nodes, body, pos_start diff --git a/src/core/parser/pos/localcalls.fy b/src/core/parser/pos/localcalls.fy index 727125d..1e2609c 100644 --- a/src/core/parser/pos/localcalls.fy +++ b/src/core/parser/pos/localcalls.fy @@ -152,19 +152,6 @@ def new_resolver((:statements, meta, nodes), var_names_avaliable): ) ) -def get_vars_defined_def_or_lambda(args, statements,var_names_avaliable): - received_arguments = args - |> Elixir.Enum.filter(lambda (node_type, _, _): - node_type in Core.Parser.Nodes.node_types_accept_pattern() - ) - |> Elixir.Enum.map(&get_variables_bound_in_pattern/1) - - statements = convert_local_function_calls( - statements, - Elixir.List.flatten(var_names_avaliable, received_arguments) - ) - - [args, statements] def new_resolver((:def, meta, [name, args, statements]), var_names_avaliable): [args, statements] = get_vars_defined_def_or_lambda( @@ -199,17 +186,6 @@ def new_resolver((:pipe, meta, [left_node, right_node]), var_names_avaliable): ] ) -def resolve_map_pair((key, value), var_names_avaliable): - ( - convert_local_function_calls(key, var_names_avaliable), - convert_local_function_calls(value, var_names_avaliable) - ) - -def resolve_map_pair((:spread, meta, [node_to_spread]), var_names_avaliable): - ( - :spread, meta, [new_resolver(node_to_spread, var_names_avaliable)] - ) - def new_resolver((:map, meta, pairs), var_names_avaliable): ( :map, @@ -257,4 +233,30 @@ def new_resolver(node <- (:range, meta, [left_node, right_node]), var_names_aval new_resolver(left_node, var_names_avaliable), new_resolver(right_node, var_names_avaliable), ] - ) \ No newline at end of file + ) + +def resolve_map_pair((key, value), var_names_avaliable): + ( + convert_local_function_calls(key, var_names_avaliable), + convert_local_function_calls(value, var_names_avaliable) + ) + +def resolve_map_pair((:spread, meta, [node_to_spread]), var_names_avaliable): + ( + :spread, meta, [new_resolver(node_to_spread, var_names_avaliable)] + ) + + +def get_vars_defined_def_or_lambda(args, statements,var_names_avaliable): + received_arguments = args + |> Elixir.Enum.filter(lambda (node_type, _, _): + node_type in Core.Parser.Nodes.node_types_accept_pattern() + ) + |> Elixir.Enum.map(&get_variables_bound_in_pattern/1) + + statements = convert_local_function_calls( + statements, + Elixir.List.flatten(var_names_avaliable, received_arguments) + ) + + [args, statements] \ No newline at end of file