Skip to content

Commit

Permalink
Support constants
Browse files Browse the repository at this point in the history
  • Loading branch information
dusty-phillips committed Aug 28, 2024
1 parent b62323b commit 9a48840
Show file tree
Hide file tree
Showing 13 changed files with 89 additions and 88 deletions.
10 changes: 3 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,6 @@ are ) in the codebase, as of the last time that I updated this list.
### Some other things I know are missing

- no let assert
- (EASY) const definitions aren't supported yet (module.constants)
- type aliases aren't supported yet (module.type_aliases)
- macabre_stdlib only has `io.println`
- Not doing anything to avoid collision between gleam identifiers with python keywords
Expand All @@ -164,10 +163,7 @@ are ) in the codebase, as of the last time that I updated this list.
1), mystr: "Foo")` in gleam
- javascript seems to solve this by automatically reordering the arguments to
match the input type
- (EASY) I notice that the javascript doesn't generate the wrapping class for custom
variants. I think we should make top level types for each constructor and then a type union
for all the types in a single class.
- Related: if you have a multi-variant type where the first constructor shadows
the type's name, it breaks
- (EASY) maybe call ruff or black on the files after they are output, if they are installed.
for all the types in a single class.
- (EASY) maybe call ruff or black on the files after they are output, if they are installed. (shellout is already available)
- Code is very not commented
- Should be putting public types, functions, and constants in `__all__`
2 changes: 0 additions & 2 deletions src/compiler.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import glance
import gleam/dict
import gleam/list
import gleam/result
import pprint

pub fn compile_module(glance_module: glance.Module) -> String {
glance_module
Expand All @@ -14,7 +13,6 @@ pub fn compile_module(glance_module: glance.Module) -> String {
}

pub fn compile_package(package: package.GleamPackage) -> package.CompiledPackage {
pprint.debug(package.modules)
package.CompiledPackage(
project: package.project,
has_main: dict.get(package.modules, package.project.name <> ".gleam")
Expand Down
8 changes: 8 additions & 0 deletions src/compiler/generator.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ pub fn generate(module: python.Module) -> String {
string_builder.new()
|> string_builder.append(python_prelude.prelude)
|> string_builder.append_builder(imports.generate_imports(module.imports))
|> string_builder.append_builder(
internal.generate_plural(
module.constants,
statements.generate_constant,
"\n",
)
|> internal.append_if_not_empty("\n\n"),
)
|> string_builder.append_builder(internal.generate_plural(
module.custom_types,
types.generate_custom_type,
Expand Down
8 changes: 8 additions & 0 deletions src/compiler/internal/generator/statements.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ pub fn generate_statement(statement: python.Statement) -> StringBuilder {
}
}

pub fn generate_constant(constant: python.Constant) -> StringBuilder {
string_builder.from_string(constant.name)
|> string_builder.append(" = ")
|> string_builder.append_builder(expressions.generate_expression(
constant.value,
))
}

fn generate_cases(cases: List(python.MatchCase)) -> StringBuilder {
case cases {
[] -> string_builder.from_string("pass")
Expand Down
36 changes: 2 additions & 34 deletions src/compiler/internal/generator/types.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,18 @@ pub fn generate_custom_type(custom_type: python.CustomType) -> StringBuilder {
// empty types get discarded
[] -> string_builder.new()

// we just discard the outer class if there is only one variant
[one_variant] -> {
internal.generate_plural(
custom_type.parameters,
generate_generic_var,
"\n",
)
|> string_builder.append_builder(generate_type_variant(one_variant))
|> string_builder.append("\n\n\n")
}

variants -> {
string_builder.from_string("// pub type " <> custom_type.name)
internal.generate_plural(
custom_type.parameters,
generate_generic_var,
"\n",
)
|> string_builder.append("class ")
|> string_builder.append(custom_type.name)
|> string_builder.append(":\n")
|> string_builder.append_builder(
internal.generate_plural(variants, generate_type_variant, "\n\n")
|> internal.indent(4)
|> internal.append_if_not_empty("\n\n"),
)
|> string_builder.append_builder(internal.generate_plural(
custom_type.variants,
generate_variant_reassign(custom_type.name),
"\n",
))
|> string_builder.append("\n\n\n")
|> string_builder.append("\n")
}
}
}
Expand Down Expand Up @@ -117,16 +98,3 @@ fn generate_type(type_: python.Type) -> StringBuilder {
|> string_builder.uppercase
}
}

fn generate_variant_reassign(
namespace: String,
) -> fn(python.Variant) -> StringBuilder {
fn(variant: python.Variant) -> StringBuilder {
string_builder.new()
|> string_builder.append(variant.name)
|> string_builder.append(" = ")
|> string_builder.append(namespace)
|> string_builder.append(".")
|> string_builder.append(variant.name)
}
}
6 changes: 6 additions & 0 deletions src/compiler/internal/transformer.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ pub type TransformerContext {
)
}

pub const empty_context = TransformerContext(
next_function_id: 0,
next_block_id: 0,
next_case_id: 0,
)

pub type ExpressionReturn {
ExpressionReturn(
context: TransformerContext,
Expand Down
28 changes: 20 additions & 8 deletions src/compiler/internal/transformer/statements.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,7 @@ import gleam/option
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
transform_statement_block_with_context(internal.empty_context, statements).statements
}

pub fn transform_statement_block_with_context(
Expand All @@ -50,6 +43,25 @@ pub fn transform_statement_block_with_context(
)
}

pub fn transform_constant(
module: python.Module,
constant: glance.Definition(glance.Constant),
) -> python.Module {
python.Module(
..module,
constants: [
python.Constant(
name: constant.definition.name,
value: transform_expression(
internal.empty_context,
constant.definition.value,
).expression,
),
..module.constants
],
)
}

fn transform_statement(
transform_context: internal.TransformerContext,
statement: glance.Statement,
Expand Down
7 changes: 6 additions & 1 deletion src/compiler/python.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ pub type BinaryOperator {
Modulo
}

pub type Constant {
Constant(name: String, value: Expression)
}

pub type Expression {
String(String)
Number(String)
Expand Down Expand Up @@ -140,9 +144,10 @@ pub type Module {
imports: List(Import),
functions: List(Function),
custom_types: List(CustomType),
constants: List(Constant),
)
}

pub fn empty_module() -> Module {
Module(imports: [], functions: [], custom_types: [])
Module(imports: [], functions: [], custom_types: [], constants: [])
}
4 changes: 3 additions & 1 deletion src/compiler/transformer.gleam
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import compiler/internal/transformer as internal
import compiler/internal/transformer/functions
import compiler/internal/transformer/statements
import compiler/internal/transformer/types
import compiler/python
import glance
Expand All @@ -10,6 +11,7 @@ import gleam/string
pub fn transform(input: glance.Module) -> python.Module {
python.empty_module()
|> list.fold(input.imports, _, transform_import)
|> list.fold(input.constants, _, statements.transform_constant)
|> list.fold(input.functions, _, transform_function_or_external)
|> list.fold(input.custom_types, _, transform_custom_type_in_module)
}
Expand Down Expand Up @@ -117,7 +119,7 @@ fn transform_custom_type_in_module(
)
}

pub fn maybe_extract_external(
fn maybe_extract_external(
function_attribute: glance.Attribute,
) -> Result(python.Import, internal.TransformError) {
case function_attribute {
Expand Down
2 changes: 0 additions & 2 deletions src/filesystem.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import filepath
import gleam/io
import gleam/list
import gleam/result
import pprint
import python_prelude
import simplifile

Expand Down Expand Up @@ -52,7 +51,6 @@ pub fn write_py_main(
build_dir: String,
module: String,
) -> Result(Nil, errors.Error) {
pprint.debug(has_main)
case has_main {
True ->
filepath.join(build_dir, "__main__.py")
Expand Down
2 changes: 0 additions & 2 deletions test/compiler/directory_structure_tests.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@ import compiler/project
import filepath
import gleam/dict
import gleam/list
import gleam/option
import gleam/set
import gleam/string
import gleeunit/should
import macabre
import pprint
import simplifile
import temporary

Expand Down
14 changes: 14 additions & 0 deletions test/compiler/expression_test.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -758,3 +758,17 @@ def main():
foo = _fn_block_0()",
)
}

pub fn const_test() {
"const foo = 5"
|> glance.module
|> should.be_ok
|> compiler.compile_module
|> should.equal(
"from gleam_builtins import *
foo = 5
",
)
}
50 changes: 19 additions & 31 deletions test/compiler/types_test.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,13 @@ pub fn multi_variant_custom_type_test() {
|> should.equal(
"from gleam_builtins import *
class Foo:
@dataclasses.dataclass(frozen=True)
class Bar:
a: int
@dataclasses.dataclass(frozen=True)
class Baz:
a: str
@dataclasses.dataclass(frozen=True)
class Bar:
a: int
Bar = Foo.Bar
Baz = Foo.Baz
@dataclasses.dataclass(frozen=True)
class Baz:
a: str
",
Expand Down Expand Up @@ -92,17 +88,13 @@ pub fn multi_variant_with_no_fields_test() {
|> should.equal(
"from gleam_builtins import *
class Foo:
@dataclasses.dataclass(frozen=True)
class Bar:
pass
@dataclasses.dataclass(frozen=True)
class Baz:
pass
@dataclasses.dataclass(frozen=True)
class Bar:
pass
Bar = Foo.Bar
Baz = Foo.Baz
@dataclasses.dataclass(frozen=True)
class Baz:
pass
",
Expand Down Expand Up @@ -160,17 +152,13 @@ pub fn multi_variant_generic_test() {
"from gleam_builtins import *
ELEM = typing.TypeVar('ELEM')
class Foo:
@dataclasses.dataclass(frozen=True)
class Bar:
item: ELEM
@dataclasses.dataclass(frozen=True)
class Baz:
elem: ELEM
Bar = Foo.Bar
Baz = Foo.Baz
@dataclasses.dataclass(frozen=True)
class Bar:
item: ELEM
@dataclasses.dataclass(frozen=True)
class Baz:
elem: ELEM
",
Expand Down

0 comments on commit 9a48840

Please sign in to comment.