+8
-4
README.md
+8
-4
README.md
···
9
9
```gleam
10
10
import gleam/io
11
11
import stare
12
+
import stare/function
13
+
import stare/value
14
+
import stare/type_
15
+
import stare/import_
12
16
13
17
pub fn main() -> Nil {
14
18
let assert Ok(code) = stare.module(
15
19
imports: [
16
-
stare.import_(
20
+
import_.import_(
17
21
module: ["gleam", "io"],
18
22
types: [],
19
23
constructors: [],
···
22
26
),
23
27
],
24
28
functions: [
25
-
stare.function(
29
+
function.function(
26
30
name: "main",
27
31
public: True,
28
32
parameters: [],
29
-
return_type: Some(type_.nil()),
33
+
return_type: Some(type_.nil),
30
34
statements: [
31
-
stare.function_call(
35
+
function.call(
32
36
module: Some("io"),
33
37
function: "println",
34
38
arguments: [stare.value(value.string("Hello World!"))],
+22
-187
src/stare.gleam
+22
-187
src/stare.gleam
···
1
1
import gleam/list
2
-
import gleam/option.{type Option}
3
2
import gleam/result
4
-
import gleam/string
5
3
import gleam/string_tree
6
4
import shellout
7
5
import simplifile
8
-
import stare/type_
6
+
import stare/function
7
+
import stare/import_
8
+
import stare/internal/statement
9
9
import stare/value
10
10
11
11
@internal
12
12
pub opaque type Module(a, b) {
13
-
Module(imports: List(Import), functions: List(Function(a, b)))
13
+
Module(
14
+
imports: List(import_.Import),
15
+
functions: List(function.Function(a, b)),
16
+
)
14
17
}
15
18
16
19
pub fn module(
17
-
imports imports: List(Import),
18
-
functions functions: List(Function(a, b)),
20
+
imports imports: List(import_.Import),
21
+
functions functions: List(function.Function(a, b)),
19
22
) -> Module(a, b) {
20
23
Module(imports:, functions:)
21
24
}
22
25
23
-
@internal
24
-
pub opaque type Import {
25
-
Import(
26
-
module: List(String),
27
-
types: List(String),
28
-
constructors: List(String),
29
-
functions: List(String),
30
-
alias: Option(String),
31
-
)
26
+
pub fn add_ints(left left: Int, right right: Int) -> statement.Statement(a, b) {
27
+
statement.AddInts(value.int(left), value.int(right))
32
28
}
33
29
34
-
pub fn import_(
35
-
module module: List(String),
36
-
types types: List(String),
37
-
constructors constructors: List(String),
38
-
functions functions: List(String),
39
-
alias alias: Option(String),
40
-
) -> Import {
41
-
Import(module:, types:, constructors:, functions:, alias:)
30
+
pub fn add_floats(
31
+
left left: Float,
32
+
right right: Float,
33
+
) -> statement.Statement(a, b) {
34
+
statement.AddFloats(value.float(left), value.float(right))
42
35
}
43
36
44
-
@internal
45
-
pub opaque type Parameter {
46
-
Parameter(name: String, label: Option(String), type_: Option(type_.Type))
37
+
pub fn value(value value: value.Value(a, b)) -> statement.Statement(a, b) {
38
+
statement.Raw(value)
47
39
}
48
40
49
-
pub fn parameter(
50
-
label label: Option(String),
51
-
name name: String,
52
-
type_ type_: Option(type_.Type),
53
-
) -> Parameter {
54
-
Parameter(name:, label:, type_:)
55
-
}
56
-
57
-
pub fn generate_parameter(parameter param: Parameter) -> String {
58
-
case param.label {
59
-
option.Some(label) -> label <> " "
60
-
option.None -> ""
61
-
}
62
-
<> param.name
63
-
<> case param.type_ {
64
-
option.Some(type_) -> ": " <> type_.to_string(type_:)
65
-
option.None -> ""
66
-
}
67
-
}
68
-
69
-
@internal
70
-
pub opaque type Statement(a, b) {
71
-
FunctionCall(
72
-
module: Option(String),
73
-
function_name: String,
74
-
arguments: List(Statement(a, b)),
75
-
)
76
-
LocalVariable(String)
77
-
Raw(value.Value(a, b))
78
-
AddInts(value.Value(a, b), value.Value(a, b))
79
-
AddFloats(value.Value(a, b), value.Value(a, b))
80
-
}
81
-
82
-
pub fn add_ints(left left: Int, right right: Int) -> Statement(a, b) {
83
-
AddInts(value.int(left), value.int(right))
84
-
}
85
-
86
-
pub fn add_floats(left left: Float, right right: Float) -> Statement(a, b) {
87
-
AddFloats(value.float(left), value.float(right))
88
-
}
89
-
90
-
pub fn value(value value: value.Value(a, b)) -> Statement(a, b) {
91
-
Raw(value)
92
-
}
93
-
94
-
pub fn local_variable(name name: String) -> Statement(a, b) {
95
-
LocalVariable(name)
96
-
}
97
-
98
-
pub fn function_call(
99
-
module module: Option(String),
100
-
function function_name: String,
101
-
arguments arguments: List(Statement(a, b)),
102
-
) -> Statement(a, b) {
103
-
FunctionCall(module:, function_name:, arguments:)
104
-
}
105
-
106
-
@internal
107
-
pub opaque type Function(a, b) {
108
-
Function(
109
-
name: String,
110
-
public: Bool,
111
-
params: List(Parameter),
112
-
type_: Option(type_.Type),
113
-
statements: List(Statement(a, b)),
114
-
)
115
-
}
116
-
117
-
pub fn function(
118
-
name name: String,
119
-
public public: Bool,
120
-
parameters params: List(Parameter),
121
-
return_type type_: Option(type_.Type),
122
-
statements statements: List(Statement(a, b)),
123
-
) -> Function(a, b) {
124
-
Function(name:, public:, params:, type_:, statements:)
125
-
}
126
-
127
-
pub fn generate_import(import_ import_: Import) -> String {
128
-
let Import(module:, types:, constructors:, functions:, alias:) = import_
129
-
let i =
130
-
"import "
131
-
<> list.fold(module, "", fn(acc, part) { acc <> part <> "/" })
132
-
|> string.drop_end(1)
133
-
134
-
let i = case types, constructors, functions {
135
-
[], [], [] -> i
136
-
_, _, _ -> {
137
-
i
138
-
<> ".{"
139
-
<> list.fold(types, "", fn(acc, type_) { acc <> "type " <> type_ <> "," })
140
-
<> list.fold(constructors, "", fn(acc, constructor) {
141
-
acc <> constructor <> ","
142
-
})
143
-
<> list.fold(functions, "", fn(acc, function) { acc <> function <> "," })
144
-
<> "}"
145
-
}
146
-
}
147
-
case alias {
148
-
option.None -> i
149
-
option.Some(alias) -> i <> " as " <> alias
150
-
}
151
-
}
152
-
153
-
pub fn generate_statement(statement statement: Statement(a, b)) -> String {
154
-
case statement {
155
-
FunctionCall(module:, function_name:, arguments:) -> {
156
-
string_tree.new()
157
-
|> string_tree.append(case module {
158
-
option.None -> ""
159
-
option.Some(module) -> module <> "."
160
-
})
161
-
|> string_tree.append(function_name)
162
-
|> string_tree.append("(")
163
-
|> string_tree.append(
164
-
list.fold(arguments, "", fn(acc, arg) {
165
-
acc <> generate_statement(arg) <> ","
166
-
}),
167
-
)
168
-
|> string_tree.append(")")
169
-
|> string_tree.to_string()
170
-
}
171
-
Raw(value) -> value.to_string(value)
172
-
AddInts(left, right) ->
173
-
value.to_string(left) <> "+" <> value.to_string(right)
174
-
AddFloats(left, right) ->
175
-
value.to_string(left) <> "+." <> value.to_string(right)
176
-
LocalVariable(string) -> string
177
-
}
178
-
}
179
-
180
-
pub fn generate_function(function function: Function(a, b)) -> String {
181
-
string_tree.new()
182
-
|> string_tree.append(case function.public {
183
-
False -> ""
184
-
True -> "pub "
185
-
})
186
-
|> string_tree.append("fn ")
187
-
|> string_tree.append(function.name <> "(")
188
-
|> string_tree.append_tree(
189
-
function.params
190
-
|> list.fold(string_tree.new(), fn(acc, param) {
191
-
string_tree.append(acc, generate_parameter(param) <> ",")
192
-
}),
193
-
)
194
-
|> string_tree.append(") ")
195
-
|> string_tree.append(case function.type_ {
196
-
option.None -> ""
197
-
option.Some(type_) -> "-> " <> type_.to_string(type_:) <> " "
198
-
})
199
-
|> string_tree.append("{\n")
200
-
|> string_tree.append_tree(
201
-
function.statements
202
-
|> list.fold(string_tree.new(), fn(acc, statement) {
203
-
string_tree.append(acc, generate_statement(statement) <> "\n")
204
-
}),
205
-
)
206
-
|> string_tree.append("}")
207
-
|> string_tree.to_string()
41
+
pub fn local_variable(name name: String) -> statement.Statement(a, b) {
42
+
statement.LocalVariable(name)
208
43
}
209
44
210
45
pub fn generate(module: Module(a, b)) -> String {
211
46
let imports =
212
47
module.imports
213
48
|> list.fold(string_tree.new(), fn(acc, import_) {
214
-
string_tree.append(acc, generate_import(import_:) <> "\n")
49
+
string_tree.append(acc, import_.generate_import(import_:) <> "\n")
215
50
})
216
51
217
52
let functions =
218
53
module.functions
219
54
|> list.fold(string_tree.new(), fn(acc, function) {
220
-
string_tree.append(acc, generate_function(function:) <> "\n")
55
+
string_tree.append(acc, function.generate_function(function:) <> "\n")
221
56
})
222
57
223
58
string_tree.new()
+95
src/stare/function.gleam
+95
src/stare/function.gleam
···
1
+
import gleam/list
2
+
import gleam/option
3
+
import gleam/string_tree
4
+
import stare/internal/statement
5
+
import stare/type_
6
+
7
+
@internal
8
+
pub opaque type Function(a, b) {
9
+
Function(
10
+
name: String,
11
+
public: Bool,
12
+
params: List(Parameter),
13
+
type_: option.Option(type_.Type),
14
+
statements: List(statement.Statement(a, b)),
15
+
)
16
+
}
17
+
18
+
@internal
19
+
pub opaque type Parameter {
20
+
Parameter(
21
+
name: String,
22
+
label: option.Option(String),
23
+
type_: option.Option(type_.Type),
24
+
)
25
+
}
26
+
27
+
pub fn call(
28
+
module module: option.Option(String),
29
+
function function_name: String,
30
+
arguments arguments: List(statement.Statement(a, b)),
31
+
) -> statement.Statement(a, b) {
32
+
statement.FunctionCall(module:, function_name:, arguments:)
33
+
}
34
+
35
+
pub fn parameter(
36
+
label label: option.Option(String),
37
+
name name: String,
38
+
type_ type_: option.Option(type_.Type),
39
+
) -> Parameter {
40
+
Parameter(name:, label:, type_:)
41
+
}
42
+
43
+
@internal
44
+
pub fn generate_parameter(parameter param: Parameter) -> String {
45
+
case param.label {
46
+
option.Some(label) -> label <> " "
47
+
option.None -> ""
48
+
}
49
+
<> param.name
50
+
<> case param.type_ {
51
+
option.Some(type_) -> ": " <> type_.to_string(type_:)
52
+
option.None -> ""
53
+
}
54
+
}
55
+
56
+
pub fn function(
57
+
name name: String,
58
+
public public: Bool,
59
+
parameters params: List(Parameter),
60
+
return_type type_: option.Option(type_.Type),
61
+
statements statements: List(statement.Statement(a, b)),
62
+
) -> Function(a, b) {
63
+
Function(name:, public:, params:, type_:, statements:)
64
+
}
65
+
66
+
@internal
67
+
pub fn generate_function(function function: Function(a, b)) -> String {
68
+
string_tree.new()
69
+
|> string_tree.append(case function.public {
70
+
False -> ""
71
+
True -> "pub "
72
+
})
73
+
|> string_tree.append("fn ")
74
+
|> string_tree.append(function.name <> "(")
75
+
|> string_tree.append_tree(
76
+
function.params
77
+
|> list.fold(string_tree.new(), fn(acc, param) {
78
+
string_tree.append(acc, generate_parameter(param) <> ",")
79
+
}),
80
+
)
81
+
|> string_tree.append(") ")
82
+
|> string_tree.append(case function.type_ {
83
+
option.None -> ""
84
+
option.Some(type_) -> "-> " <> type_.to_string(type_:) <> " "
85
+
})
86
+
|> string_tree.append("{\n")
87
+
|> string_tree.append_tree(
88
+
function.statements
89
+
|> list.fold(string_tree.new(), fn(acc, statement) {
90
+
string_tree.append(acc, statement.generate_statement(statement) <> "\n")
91
+
}),
92
+
)
93
+
|> string_tree.append("}")
94
+
|> string_tree.to_string()
95
+
}
+51
src/stare/import_.gleam
+51
src/stare/import_.gleam
···
1
+
import gleam/list
2
+
import gleam/option
3
+
import gleam/string
4
+
5
+
@internal
6
+
pub opaque type Import {
7
+
Import(
8
+
module: List(String),
9
+
types: List(String),
10
+
constructors: List(String),
11
+
functions: List(String),
12
+
alias: option.Option(String),
13
+
)
14
+
}
15
+
16
+
pub fn import_(
17
+
module module: List(String),
18
+
types types: List(String),
19
+
constructors constructors: List(String),
20
+
functions functions: List(String),
21
+
alias alias: option.Option(String),
22
+
) -> Import {
23
+
Import(module:, types:, constructors:, functions:, alias:)
24
+
}
25
+
26
+
@internal
27
+
pub fn generate_import(import_ import_: Import) -> String {
28
+
let Import(module:, types:, constructors:, functions:, alias:) = import_
29
+
let i =
30
+
"import "
31
+
<> list.fold(module, "", fn(acc, part) { acc <> part <> "/" })
32
+
|> string.drop_end(1)
33
+
34
+
let i = case types, constructors, functions {
35
+
[], [], [] -> i
36
+
_, _, _ -> {
37
+
i
38
+
<> ".{"
39
+
<> list.fold(types, "", fn(acc, type_) { acc <> "type " <> type_ <> "," })
40
+
<> list.fold(constructors, "", fn(acc, constructor) {
41
+
acc <> constructor <> ","
42
+
})
43
+
<> list.fold(functions, "", fn(acc, function) { acc <> function <> "," })
44
+
<> "}"
45
+
}
46
+
}
47
+
case alias {
48
+
option.None -> i
49
+
option.Some(alias) -> i <> " as " <> alias
50
+
}
51
+
}
+45
src/stare/internal/statement.gleam
+45
src/stare/internal/statement.gleam
···
1
+
import gleam/list
2
+
import gleam/option
3
+
import gleam/string_tree
4
+
import stare/value
5
+
6
+
@internal
7
+
pub type Statement(a, b) {
8
+
FunctionCall(
9
+
module: option.Option(String),
10
+
function_name: String,
11
+
arguments: List(Statement(a, b)),
12
+
)
13
+
LocalVariable(String)
14
+
Raw(value.Value(a, b))
15
+
AddInts(value.Value(a, b), value.Value(a, b))
16
+
AddFloats(value.Value(a, b), value.Value(a, b))
17
+
}
18
+
19
+
@internal
20
+
pub fn generate_statement(statement statement: Statement(a, b)) -> String {
21
+
case statement {
22
+
FunctionCall(module:, function_name:, arguments:) -> {
23
+
string_tree.new()
24
+
|> string_tree.append(case module {
25
+
option.None -> ""
26
+
option.Some(module) -> module <> "."
27
+
})
28
+
|> string_tree.append(function_name)
29
+
|> string_tree.append("(")
30
+
|> string_tree.append(
31
+
list.fold(arguments, "", fn(acc, arg) {
32
+
acc <> generate_statement(arg) <> ","
33
+
}),
34
+
)
35
+
|> string_tree.append(")")
36
+
|> string_tree.to_string()
37
+
}
38
+
Raw(value) -> value.to_string(value)
39
+
AddInts(left, right) ->
40
+
value.to_string(left) <> "+" <> value.to_string(right)
41
+
AddFloats(left, right) ->
42
+
value.to_string(left) <> "+." <> value.to_string(right)
43
+
LocalVariable(string) -> string
44
+
}
45
+
}
+41
-45
test/stare_test.gleam
+41
-45
test/stare_test.gleam
···
2
2
import gleam/option.{None, Some}
3
3
import gleeunit
4
4
import stare
5
+
import stare/function
6
+
import stare/import_
5
7
import stare/type_
6
8
import stare/value
7
9
···
12
14
pub fn labelled_param_test() {
13
15
let module =
14
16
stare.module(imports: [], functions: [
15
-
stare.function(
17
+
function.function(
16
18
name: "my_function",
17
19
public: False,
18
20
parameters: [
19
-
stare.parameter(label: None, name: "wibble", type_: None),
20
-
stare.parameter(label: None, name: "wobble", type_: Some(type_.int)),
21
-
stare.parameter(
21
+
function.parameter(label: None, name: "wibble", type_: None),
22
+
function.parameter(
23
+
label: None,
24
+
name: "wobble",
25
+
type_: Some(type_.int),
26
+
),
27
+
function.parameter(
22
28
label: Some("label"),
23
29
name: "name",
24
30
type_: Some(type_.string),
···
40
46
let module =
41
47
stare.module(
42
48
imports: [
43
-
stare.import_(
49
+
import_.import_(
44
50
module: ["gleam", "option"],
45
51
types: [],
46
52
constructors: ["Some"],
···
49
55
),
50
56
],
51
57
functions: [
52
-
stare.function(
58
+
function.function(
53
59
name: "do_thing",
54
60
public: False,
55
61
parameters: [
56
-
stare.parameter(
62
+
function.parameter(
57
63
label: None,
58
64
name: "option",
59
65
type_: Some(type_.option(qualified: True, some: type_.string)),
···
61
67
],
62
68
return_type: None,
63
69
statements: [
64
-
stare.function_call(
70
+
function.call(
65
71
module: Some("option"),
66
72
function: "unwrap",
67
73
arguments: [
···
71
77
),
72
78
],
73
79
),
74
-
stare.function(
80
+
function.function(
75
81
name: "main",
76
82
public: True,
77
83
parameters: [],
78
84
return_type: None,
79
85
statements: [
80
-
stare.function_call(module: None, function: "do_thing", arguments: [
86
+
function.call(module: None, function: "do_thing", arguments: [
81
87
stare.value(value.option(
82
88
qualified: False,
83
89
option: Some(value.string("")),
···
99
105
let module =
100
106
stare.module(
101
107
imports: [
102
-
stare.import_(
108
+
import_.import_(
103
109
module: ["gleam", "io"],
104
110
types: [],
105
111
constructors: [],
106
112
functions: [],
107
113
alias: None,
108
114
),
109
-
stare.import_(
115
+
import_.import_(
110
116
module: ["gleam", "int"],
111
117
types: [],
112
118
constructors: [],
···
115
121
),
116
122
],
117
123
functions: [
118
-
stare.function(
124
+
function.function(
119
125
name: "main",
120
126
public: True,
121
127
parameters: [],
122
128
return_type: None,
123
129
statements: [
124
-
stare.function_call(
125
-
module: Some("io"),
126
-
function: "println",
127
-
arguments: [
128
-
stare.function_call(
129
-
module: Some("int"),
130
-
function: "to_string",
131
-
arguments: [stare.add_ints(1, 2)],
132
-
),
133
-
],
134
-
),
130
+
function.call(module: Some("io"), function: "println", arguments: [
131
+
function.call(
132
+
module: Some("int"),
133
+
function: "to_string",
134
+
arguments: [stare.add_ints(1, 2)],
135
+
),
136
+
]),
135
137
],
136
138
),
137
139
],
···
148
150
let module =
149
151
stare.module(
150
152
imports: [
151
-
stare.import_(
153
+
import_.import_(
152
154
module: ["gleam", "io"],
153
155
types: [],
154
156
constructors: [],
155
157
functions: [],
156
158
alias: None,
157
159
),
158
-
stare.import_(
160
+
import_.import_(
159
161
module: ["gleam", "float"],
160
162
types: [],
161
163
constructors: [],
···
164
166
),
165
167
],
166
168
functions: [
167
-
stare.function(
169
+
function.function(
168
170
name: "main",
169
171
public: True,
170
172
parameters: [],
171
173
return_type: None,
172
174
statements: [
173
-
stare.function_call(
174
-
module: Some("io"),
175
-
function: "println",
176
-
arguments: [
177
-
stare.function_call(
178
-
module: Some("float"),
179
-
function: "to_string",
180
-
arguments: [stare.add_floats(1.1, 2.2)],
181
-
),
182
-
],
183
-
),
175
+
function.call(module: Some("io"), function: "println", arguments: [
176
+
function.call(
177
+
module: Some("float"),
178
+
function: "to_string",
179
+
arguments: [stare.add_floats(1.1, 2.2)],
180
+
),
181
+
]),
184
182
],
185
183
),
186
184
],
···
197
195
let module =
198
196
stare.module(
199
197
imports: [
200
-
stare.import_(
198
+
import_.import_(
201
199
module: ["gleam", "io"],
202
200
types: [],
203
201
constructors: [],
···
206
204
),
207
205
],
208
206
functions: [
209
-
stare.function(
207
+
function.function(
210
208
name: "main",
211
209
public: True,
212
210
parameters: [],
213
211
return_type: Some(type_.nil),
214
212
statements: [
215
-
stare.function_call(
216
-
module: Some("io"),
217
-
function: "println",
218
-
arguments: [stare.value(value.string("Hello World!"))],
219
-
),
213
+
function.call(module: Some("io"), function: "println", arguments: [
214
+
stare.value(value.string("Hello World!")),
215
+
]),
220
216
],
221
217
),
222
218
],