diff --git a/README.md b/README.md index 40f3781..98b6ee3 100644 --- a/README.md +++ b/README.md @@ -60,10 +60,6 @@ are ) in the codebase, as of the last time that I updated this list. - (EASY) Discard parameters in function arguments are not transformed - Bitstrings are not supported yet - case guards are not supported yet -- block case expressions are not supported yet. - - this could be trivially solved by just letting it fall through to the expression arm, - which would generate an extra function, but it should be possible to put those - statements right in the case itself - Functions as type fields are not supported yet - debatable whether to make them a `def` right on the class or have the def be defined somewhere and just attach it like other fields - Fields that are "HoleType" are not supported and I don't even know what that means diff --git a/src/compiler/generator.gleam b/src/compiler/generator.gleam index 2d769f2..29ec2c1 100644 --- a/src/compiler/generator.gleam +++ b/src/compiler/generator.gleam @@ -4,7 +4,6 @@ import gleam/int import gleam/list import gleam/option import gleam/string_builder.{type StringBuilder} -import pprint import python_prelude fn generate_import(import_: python.Import) -> StringBuilder { @@ -180,9 +179,7 @@ fn generate_expression(expression: python.Expression) { fn generate_statement(statement: python.Statement) -> StringBuilder { case statement { - python.Expression(expression) -> - generate_expression(expression) - |> internal.append_if_not_empty("\n") + python.Expression(expression) -> generate_expression(expression) python.Return(expression) -> string_builder.from_string("return ") |> string_builder.append_builder(generate_expression(expression)) diff --git a/src/compiler/internal/transformer/statements.gleam b/src/compiler/internal/transformer/statements.gleam index 282c712..416c28c 100644 --- a/src/compiler/internal/transformer/statements.gleam +++ b/src/compiler/internal/transformer/statements.gleam @@ -17,17 +17,24 @@ import pprint pub fn transform_statement_block( statements: List(glance.Statement), ) -> List(python.Statement) { + transform_statement_block_with_context( + internal.TransformerContext( + next_function_id: 0, + next_block_id: 0, + next_case_id: 0, + ), + statements, + ).statements +} + +pub fn transform_statement_block_with_context( + context: internal.TransformerContext, + statements: List(glance.Statement), +) -> internal.StatementReturn { let result = statements |> list.fold( - internal.StatementReturn( - context: internal.TransformerContext( - next_function_id: 0, - next_block_id: 0, - next_case_id: 0, - ), - statements: [], - ), + internal.StatementReturn(context, statements: []), fn(state, next_statement) { let result = transform_statement(state.context, next_statement) internal.StatementReturn( @@ -36,8 +43,12 @@ pub fn transform_statement_block( ) }, ) - result.statements - |> internal.transform_last(internal.add_return_if_returnable_expression) + + internal.StatementReturn( + ..result, + statements: result.statements + |> internal.transform_last(internal.add_return_if_returnable_expression), + ) } fn transform_statement( @@ -401,8 +412,19 @@ fn fold_case_clause( glance.Clause(guard: option.Some(_), ..) -> todo as "Case guards not implemented yet" - glance.Clause([pattern_list], option.None, glance.Block(_statements)) -> { - todo as "block case clauses not supported yet" + glance.Clause(pattern_list, option.None, glance.Block(statements)) -> { + let python_pattern = patterns.transform_alternative_patterns(pattern_list) + let statements_result = + transform_statement_block_with_context(state.context, statements) + internal.TransformState( + statements_result.context, + state.statements, + state.item + |> list.prepend(python.MatchCase( + python_pattern, + statements_result.statements, + )), + ) } glance.Clause(pattern_list, option.None, body) -> { diff --git a/test/case_test.gleam b/test/case_test.gleam index b2fa39f..1958d3e 100644 --- a/test/case_test.gleam +++ b/test/case_test.gleam @@ -189,3 +189,30 @@ def main(): return _fn_case_0((1, 2))", ) } + +pub fn case_block_test() { + "pub fn main() { + case 1 { + 1 -> { + let x = 1 + let y = 2 + x + y + } + } + } + " + |> compiler.compile + |> should.be_ok + |> should.equal( + "from gleam_builtins import * + +def main(): + def _fn_case_0(_case_subject): + match _case_subject: + case 1: + x = 1 + y = 2 + return x + y + return _fn_case_0(1)", + ) +} diff --git a/test/expression_test.gleam b/test/expression_test.gleam index e0e0484..c879122 100644 --- a/test/expression_test.gleam +++ b/test/expression_test.gleam @@ -181,8 +181,7 @@ pub fn empty_panic_test() { "from gleam_builtins import * def main(): - raise GleamPanic(\"panic expression evaluated\") - ", + raise GleamPanic(\"panic expression evaluated\")", ) } @@ -196,8 +195,7 @@ pub fn string_panic_test() { "from gleam_builtins import * def main(): - raise GleamPanic(\"my custom panic\") - ", + raise GleamPanic(\"my custom panic\")", ) } @@ -211,8 +209,7 @@ pub fn empty_todo_test() { "from gleam_builtins import * def main(): - raise NotImplementedError(\"This has not yet been implemented\") - ", + raise NotImplementedError(\"This has not yet been implemented\")", ) } @@ -226,8 +223,7 @@ pub fn string_todo_test() { "from gleam_builtins import * def main(): - raise NotImplementedError(\"much is yet to be done\") - ", + raise NotImplementedError(\"much is yet to be done\")", ) }