+16
birdie_snapshots/imported_type.accepted
+16
birdie_snapshots/imported_type.accepted
···
1
+
---
2
+
version: 1.4.0
3
+
title: Imported type
4
+
file: ./test/stare_test.gleam
5
+
test_name: use_imported_types_test
6
+
---
7
+
import gleam/option.{Some}
8
+
9
+
fn do_thing(option: option.Option(String)) {
10
+
option.unwrap(option, "unwrapped")
11
+
}
12
+
13
+
pub fn main() {
14
+
do_thing(Some(""))
15
+
}
16
+
+10
birdie_snapshots/mixed_parameters.accepted
+10
birdie_snapshots/mixed_parameters.accepted
+47
-23
src/stare.gleam
+47
-23
src/stare.gleam
···
9
9
import stare/value
10
10
11
11
@internal
12
-
pub opaque type Module {
13
-
Module(imports: List(Import), functions: List(Function))
12
+
pub opaque type Module(a, b) {
13
+
Module(imports: List(Import), functions: List(Function(a, b)))
14
14
}
15
15
16
16
pub fn module(
17
17
imports imports: List(Import),
18
-
functions functions: List(Function),
19
-
) -> Module {
18
+
functions functions: List(Function(a, b)),
19
+
) -> Module(a, b) {
20
20
Module(imports:, functions:)
21
21
}
22
22
···
54
54
Parameter(name:, label:, type_:)
55
55
}
56
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
+
57
69
@internal
58
-
pub opaque type Statement {
70
+
pub opaque type Statement(a, b) {
59
71
FunctionCall(
60
72
module: Option(String),
61
73
function_name: String,
62
-
arguments: List(Statement),
74
+
arguments: List(Statement(a, b)),
63
75
)
64
-
Raw(value.Value)
65
-
AddInts(value.Value, value.Value)
66
-
AddFloats(value.Value, value.Value)
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))
67
80
}
68
81
69
-
pub fn add_ints(left left: Int, right right: Int) -> Statement {
82
+
pub fn add_ints(left left: Int, right right: Int) -> Statement(a, b) {
70
83
AddInts(value.int(left), value.int(right))
71
84
}
72
85
73
-
pub fn add_floats(left left: Float, right right: Float) -> Statement {
86
+
pub fn add_floats(left left: Float, right right: Float) -> Statement(a, b) {
74
87
AddFloats(value.float(left), value.float(right))
75
88
}
76
89
77
-
pub fn value(value value: value.Value) -> Statement {
90
+
pub fn value(value value: value.Value(a, b)) -> Statement(a, b) {
78
91
Raw(value)
79
92
}
80
93
94
+
pub fn local_variable(name name: String) -> Statement(a, b) {
95
+
LocalVariable(name)
96
+
}
97
+
81
98
pub fn function_call(
82
99
module module: Option(String),
83
100
function function_name: String,
84
-
arguments arguments: List(Statement),
85
-
) -> Statement {
101
+
arguments arguments: List(Statement(a, b)),
102
+
) -> Statement(a, b) {
86
103
FunctionCall(module:, function_name:, arguments:)
87
104
}
88
105
89
106
@internal
90
-
pub opaque type Function {
107
+
pub opaque type Function(a, b) {
91
108
Function(
92
109
name: String,
93
110
public: Bool,
94
111
params: List(Parameter),
95
112
type_: Option(type_.Type),
96
-
statements: List(Statement),
113
+
statements: List(Statement(a, b)),
97
114
)
98
115
}
99
116
···
102
119
public public: Bool,
103
120
parameters params: List(Parameter),
104
121
return_type type_: Option(type_.Type),
105
-
statements statements: List(Statement),
106
-
) -> Function {
122
+
statements statements: List(Statement(a, b)),
123
+
) -> Function(a, b) {
107
124
Function(name:, public:, params:, type_:, statements:)
108
125
}
109
126
···
133
150
}
134
151
}
135
152
136
-
pub fn generate_statement(statement statement: Statement) -> String {
153
+
pub fn generate_statement(statement statement: Statement(a, b)) -> String {
137
154
case statement {
138
-
FunctionCall(module:, function_name:, arguments: _) -> {
155
+
FunctionCall(module:, function_name:, arguments:) -> {
139
156
string_tree.new()
140
157
|> string_tree.append(case module {
141
158
option.None -> ""
···
144
161
|> string_tree.append(function_name)
145
162
|> string_tree.append("(")
146
163
|> string_tree.append(
147
-
list.fold(statement.arguments, "", fn(acc, arg) {
164
+
list.fold(arguments, "", fn(acc, arg) {
148
165
acc <> generate_statement(arg) <> ","
149
166
}),
150
167
)
···
156
173
value.to_string(left) <> "+" <> value.to_string(right)
157
174
AddFloats(left, right) ->
158
175
value.to_string(left) <> "+." <> value.to_string(right)
176
+
LocalVariable(string) -> string
159
177
}
160
178
}
161
179
162
-
pub fn generate_function(function function: Function) -> String {
180
+
pub fn generate_function(function function: Function(a, b)) -> String {
163
181
string_tree.new()
164
182
|> string_tree.append(case function.public {
165
183
False -> ""
···
167
185
})
168
186
|> string_tree.append("fn ")
169
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
+
)
170
194
|> string_tree.append(") ")
171
195
|> string_tree.append(case function.type_ {
172
196
option.None -> ""
···
183
207
|> string_tree.to_string()
184
208
}
185
209
186
-
pub fn generate(module: Module) -> String {
210
+
pub fn generate(module: Module(a, b)) -> String {
187
211
let imports =
188
212
module.imports
189
213
|> list.fold(string_tree.new(), fn(acc, import_) {
+154
-6
src/stare/type_.gleam
+154
-6
src/stare/type_.gleam
···
1
+
import gleam/list
2
+
1
3
@internal
2
4
pub type Constructor
3
5
···
9
11
opaque_: Bool,
10
12
constructors: List(Constructor),
11
13
)
14
+
GenericType(name: String)
12
15
NilType
13
16
StringType
17
+
IntType
18
+
FloatType
19
+
BoolType
20
+
ListType
21
+
BitArrayType
22
+
StringTreeType(qualified: Bool)
23
+
BytesTreeType(qualified: Bool)
24
+
DictType(qualified: Bool, key: Type, value: Type)
25
+
DynamicType(qualified: Bool, decode: Bool)
26
+
DecoderType(qualified: Bool, type_: Type)
27
+
DecodeErrorType(qualified: Bool)
28
+
ContinueOrStopType(qualified: Bool, type_: Type)
29
+
OptionType(qualified: Bool, some: Type)
30
+
OrderType(qualified: Bool)
31
+
TupleType(items: List(Type))
32
+
ResultType(ok: Type, error: Type)
33
+
SetType(qualified: Bool, type_: Type)
34
+
UriType(qualified: Bool)
14
35
}
15
36
16
37
@internal
17
38
pub fn to_string(type_ type_: Type) -> String {
39
+
let qual = fn(q, x, y) {
40
+
case q {
41
+
True -> x
42
+
False -> y
43
+
}
44
+
}
45
+
18
46
case type_ {
19
47
CustomType(name:, public: _, opaque_: _, constructors: _) -> name
20
48
NilType -> "Nil"
21
49
StringType -> "String"
50
+
BitArrayType -> "BitArray"
51
+
BoolType -> "Bool"
52
+
BytesTreeType(qualified:) ->
53
+
qual(qualified, "bytes_tree.BytesTree", "BytesTree")
54
+
ContinueOrStopType(qualified:, type_:) ->
55
+
qual(qualified, "list.ContinueOrStop", "ContinueOrStop")
56
+
<> "("
57
+
<> to_string(type_)
58
+
<> ")"
59
+
DecodeErrorType(qualified:) ->
60
+
qual(qualified, "decode.DecodeError", "DecodeError")
61
+
DecoderType(qualified:, type_:) ->
62
+
qual(qualified, "decode.Decoder", "Decoder")
63
+
<> "("
64
+
<> to_string(type_)
65
+
<> ")"
66
+
DictType(qualified:, key:, value:) ->
67
+
qual(qualified, "dict.Dict", "Dict")
68
+
<> "("
69
+
<> to_string(key)
70
+
<> ","
71
+
<> to_string(value)
72
+
<> ")"
73
+
DynamicType(qualified:, decode:) ->
74
+
qual(
75
+
qualified,
76
+
qual(decode, "decode.Dynamic", "dynamic.Dynamic"),
77
+
"Dynamic",
78
+
)
79
+
FloatType -> "Float"
80
+
IntType -> "Int"
81
+
ListType -> "List"
82
+
OptionType(qualified:, some:) ->
83
+
qual(qualified, "option.Option", "Option")
84
+
<> "("
85
+
<> to_string(some)
86
+
<> ")"
87
+
OrderType(qualified:) -> qual(qualified, "order.Order", "Order")
88
+
ResultType(ok:, error:) ->
89
+
"Result" <> "(" <> to_string(ok) <> "," <> to_string(error) <> ")"
90
+
SetType(qualified:, type_:) ->
91
+
qual(qualified, "set.Set", "Set") <> "(" <> to_string(type_) <> ")"
92
+
StringTreeType(qualified:) ->
93
+
qual(qualified, "string_tree.StringTree", "StringTree")
94
+
TupleType(items:) ->
95
+
"#("
96
+
<> list.fold(items, "", fn(acc, item) { acc <> to_string(item) <> "," })
97
+
<> ")"
98
+
UriType(qualified:) -> qual(qualified, "uri.Uri", "Uri")
99
+
GenericType(name:) -> name
22
100
}
23
101
}
24
102
25
-
pub fn nil() -> Type {
26
-
NilType
27
-
}
103
+
pub const nil: Type = NilType
28
104
29
-
pub fn string() -> Type {
30
-
StringType
31
-
}
105
+
pub const string: Type = StringType
106
+
107
+
pub const int: Type = IntType
108
+
109
+
pub const float: Type = FloatType
110
+
111
+
pub const bool: Type = BoolType
112
+
113
+
pub const list: Type = ListType
114
+
115
+
pub const bit_array: Type = BitArrayType
32
116
33
117
pub fn custom(
34
118
name name: String,
···
38
122
) -> Type {
39
123
CustomType(name:, public:, opaque_:, constructors:)
40
124
}
125
+
126
+
pub fn string_tree(qualified qualified: Bool) -> Type {
127
+
StringTreeType(qualified:)
128
+
}
129
+
130
+
pub fn bytes_tree(qualified qualified: Bool) -> Type {
131
+
BytesTreeType(qualified:)
132
+
}
133
+
134
+
pub fn dict(qualified qualified: Bool, key key: Type, value value: Type) -> Type {
135
+
DictType(qualified:, key:, value:)
136
+
}
137
+
138
+
pub fn dynamic(qualified qualified: Bool) -> Type {
139
+
DynamicType(qualified:, decode: False)
140
+
}
141
+
142
+
pub fn decode_dynamic(qualified qualified: Bool) -> Type {
143
+
DynamicType(qualified:, decode: True)
144
+
}
145
+
146
+
pub fn decoder(qualified qualified: Bool, type_ type_: Type) -> Type {
147
+
DecoderType(qualified:, type_:)
148
+
}
149
+
150
+
pub fn decode_error(qualified qualified: Bool) -> Type {
151
+
DecodeErrorType(qualified)
152
+
}
153
+
154
+
pub fn continue_or_stop(qualified qualified: Bool, type_ type_: Type) -> Type {
155
+
ContinueOrStopType(qualified:, type_:)
156
+
}
157
+
158
+
pub fn option(qualified qualified: Bool, some some: Type) -> Type {
159
+
OptionType(qualified:, some:)
160
+
}
161
+
162
+
pub fn order(qualified qualified: Bool) -> Type {
163
+
OrderType(qualified:)
164
+
}
165
+
166
+
pub fn tuple(items items: List(Type)) -> Type {
167
+
TupleType(items:)
168
+
}
169
+
170
+
pub fn pair(left left: Type, right right: Type) -> Type {
171
+
TupleType([left, right])
172
+
}
173
+
174
+
pub fn result(ok ok: Type, error error: Type) -> Type {
175
+
ResultType(ok:, error:)
176
+
}
177
+
178
+
pub fn set(qualified qualified: Bool, type_ type_: Type) -> Type {
179
+
SetType(qualified:, type_:)
180
+
}
181
+
182
+
pub fn uri(qualified qualified: Bool) -> Type {
183
+
UriType(qualified:)
184
+
}
185
+
186
+
pub fn generic(name name: String) -> Type {
187
+
GenericType(name:)
188
+
}
+167
-12
src/stare/value.gleam
+167
-12
src/stare/value.gleam
···
1
+
import gleam/bit_array
2
+
import gleam/bool
3
+
import gleam/dynamic/decode
1
4
import gleam/float
2
5
import gleam/int
6
+
import gleam/list
7
+
import gleam/option
8
+
import gleam/order
9
+
import gleam/uri
3
10
4
11
@internal
5
-
pub opaque type Value {
12
+
pub opaque type Value(a, b) {
13
+
// CustomValue
6
14
NilValue
7
-
StringValue(String)
8
-
IntValue(Int)
9
-
FloatValue(Float)
15
+
StringValue(string: String)
16
+
IntValue(int: Int)
17
+
FloatValue(float: Float)
18
+
BoolValue(bool: Bool)
19
+
ListValue(list: List(Value(a, b)))
20
+
BitArrayValue(bit_array: BitArray)
21
+
DecodeErrorValue(qualified: Bool, decode_error: decode.DecodeError)
22
+
ContinueOrStopValue(qualified: Bool, cos: list.ContinueOrStop(Value(a, b)))
23
+
OptionValue(qualified: Bool, option: option.Option(Value(a, b)))
24
+
OrderValue(qualified: Bool, order: order.Order)
25
+
TupleValue(items: List(Value(a, b)))
26
+
ResultValue(result: Result(Value(a, b), Value(a, b)))
27
+
UriValue(qualified: Bool, uri: uri.Uri)
10
28
}
11
29
12
30
@internal
13
-
pub fn to_string(value value: Value) -> String {
31
+
pub fn to_string(value value: Value(a, b)) -> String {
14
32
case value {
15
33
NilValue -> "Nil"
16
34
StringValue(v) -> "\"" <> v <> "\""
17
35
IntValue(v) -> int.to_string(v)
18
36
FloatValue(v) -> float.to_string(v)
37
+
BitArrayValue(bit_array:) -> bit_array.inspect(bit_array)
38
+
BoolValue(bool:) -> bool.to_string(bool)
39
+
ContinueOrStopValue(qualified:, cos:) -> {
40
+
case qualified {
41
+
True -> "list."
42
+
_ -> ""
43
+
}
44
+
<> case cos {
45
+
list.Continue(value) -> "Continue(" <> to_string(value:) <> ")"
46
+
list.Stop(value) -> "Stop(" <> to_string(value:) <> ")"
47
+
}
48
+
}
49
+
DecodeErrorValue(qualified:, decode_error:) ->
50
+
case qualified {
51
+
True -> "decode."
52
+
False -> ""
53
+
}
54
+
<> "DecodeError(expected: "
55
+
<> to_string(string(decode_error.expected))
56
+
<> ", "
57
+
<> "found: "
58
+
<> to_string(string(decode_error.found))
59
+
<> ", "
60
+
<> "path: "
61
+
<> to_string(list(decode_error.path |> list.map(string)))
62
+
ListValue(list:) ->
63
+
"["
64
+
<> list.fold(list, "", fn(acc, item) { acc <> to_string(item) <> "," })
65
+
<> "]"
66
+
OptionValue(qualified:, option:) ->
67
+
case qualified {
68
+
True -> "option."
69
+
_ -> ""
70
+
}
71
+
<> case option {
72
+
option.None -> "None"
73
+
option.Some(value) -> "Some(" <> to_string(value:) <> ")"
74
+
}
75
+
OrderValue(qualified:, order:) ->
76
+
case qualified {
77
+
True -> "order."
78
+
False -> ""
79
+
}
80
+
<> case order {
81
+
order.Eq -> "Eq"
82
+
order.Gt -> "Gt"
83
+
order.Lt -> "Lt"
84
+
}
85
+
ResultValue(result:) ->
86
+
case result {
87
+
Ok(value) -> "Ok(" <> to_string(value) <> ")"
88
+
Error(value) -> "Error(" <> to_string(value) <> ")"
89
+
}
90
+
TupleValue(items:) ->
91
+
"#("
92
+
<> list.fold(items, "", fn(acc, item) { acc <> to_string(item) <> "," })
93
+
<> ")"
94
+
UriValue(qualified:, uri:) ->
95
+
case qualified {
96
+
True -> "uri."
97
+
False -> ""
98
+
}
99
+
<> "Uri("
100
+
<> "scheme: "
101
+
<> to_string(option(qualified, uri.scheme |> option.map(string)))
102
+
<> ","
103
+
<> "userinfo: "
104
+
<> to_string(option(qualified, uri.userinfo |> option.map(string)))
105
+
<> ","
106
+
<> "host: "
107
+
<> to_string(option(qualified, uri.host |> option.map(string)))
108
+
<> ","
109
+
<> "port: "
110
+
<> to_string(option(qualified, uri.port |> option.map(int)))
111
+
<> ","
112
+
<> "path: "
113
+
<> to_string(string(uri.path))
114
+
<> ","
115
+
<> "query: "
116
+
<> to_string(option(qualified, uri.query |> option.map(string)))
117
+
<> ","
118
+
<> "fragment: "
119
+
<> to_string(option(qualified, uri.fragment |> option.map(string)))
120
+
<> ")"
19
121
}
20
122
}
21
123
22
-
pub fn nil() -> Value {
124
+
pub fn nil() -> Value(a, b) {
23
125
NilValue
24
126
}
25
127
26
-
pub fn string(string string: String) -> Value {
27
-
StringValue(string)
128
+
pub fn string(string string: String) -> Value(a, b) {
129
+
StringValue(string:)
130
+
}
131
+
132
+
pub fn int(int int: Int) -> Value(a, b) {
133
+
IntValue(int:)
134
+
}
135
+
136
+
pub fn float(float float: Float) -> Value(a, b) {
137
+
FloatValue(float:)
138
+
}
139
+
140
+
pub fn bool(bool bool: Bool) -> Value(a, b) {
141
+
BoolValue(bool:)
142
+
}
143
+
144
+
pub fn list(list list: List(Value(a, b))) -> Value(a, b) {
145
+
ListValue(list:)
146
+
}
147
+
148
+
pub fn bit_array(bit_array bit_array: BitArray) -> Value(a, b) {
149
+
BitArrayValue(bit_array:)
28
150
}
29
151
30
-
pub fn int(int int: Int) -> Value {
31
-
IntValue(int)
152
+
pub fn decode_error(
153
+
qualified qualified: Bool,
154
+
decode_error decode_error: decode.DecodeError,
155
+
) -> Value(a, b) {
156
+
DecodeErrorValue(qualified:, decode_error:)
32
157
}
33
158
34
-
pub fn float(float float: Float) -> Value {
35
-
FloatValue(float)
159
+
pub fn continue_or_stop(
160
+
qualified qualified: Bool,
161
+
continue_or_stop cos: list.ContinueOrStop(Value(a, b)),
162
+
) -> Value(a, b) {
163
+
ContinueOrStopValue(qualified:, cos:)
164
+
}
165
+
166
+
pub fn option(
167
+
qualified qualified: Bool,
168
+
option option: option.Option(Value(a, b)),
169
+
) -> Value(a, b) {
170
+
OptionValue(qualified:, option:)
171
+
}
172
+
173
+
pub fn order(qualified qualified: Bool, order order: order.Order) -> Value(a, b) {
174
+
OrderValue(qualified:, order:)
175
+
}
176
+
177
+
pub fn tuple(items items: List(Value(a, b))) -> Value(a, b) {
178
+
TupleValue(items:)
179
+
}
180
+
181
+
pub fn pair(left left: Value(a, b), right right: Value(a, b)) -> Value(a, b) {
182
+
TupleValue([left, right])
183
+
}
184
+
185
+
pub fn result(result result: Result(Value(a, b), Value(a, b))) -> Value(a, b) {
186
+
ResultValue(result:)
187
+
}
188
+
189
+
pub fn uri(qualified qualified: Bool, uri uri: uri.Uri) -> Value(a, b) {
190
+
UriValue(qualified:, uri:)
36
191
}
+87
-1
test/stare_test.gleam
+87
-1
test/stare_test.gleam
···
9
9
gleeunit.main()
10
10
}
11
11
12
+
pub fn labelled_param_test() {
13
+
let module =
14
+
stare.module(imports: [], functions: [
15
+
stare.function(
16
+
name: "my_function",
17
+
public: False,
18
+
parameters: [
19
+
stare.parameter(label: None, name: "wibble", type_: None),
20
+
stare.parameter(label: None, name: "wobble", type_: Some(type_.int)),
21
+
stare.parameter(
22
+
label: Some("label"),
23
+
name: "name",
24
+
type_: Some(type_.string),
25
+
),
26
+
],
27
+
return_type: None,
28
+
statements: [stare.value(value.string("Testing!"))],
29
+
),
30
+
])
31
+
32
+
module
33
+
|> stare.generate()
34
+
|> stare.format()
35
+
|> assert_ok()
36
+
|> birdie.snap("Mixed Parameters")
37
+
}
38
+
39
+
pub fn use_imported_types_test() {
40
+
let module =
41
+
stare.module(
42
+
imports: [
43
+
stare.import_(
44
+
module: ["gleam", "option"],
45
+
types: [],
46
+
constructors: ["Some"],
47
+
functions: [],
48
+
alias: None,
49
+
),
50
+
],
51
+
functions: [
52
+
stare.function(
53
+
name: "do_thing",
54
+
public: False,
55
+
parameters: [
56
+
stare.parameter(
57
+
label: None,
58
+
name: "option",
59
+
type_: Some(type_.option(qualified: True, some: type_.string)),
60
+
),
61
+
],
62
+
return_type: None,
63
+
statements: [
64
+
stare.function_call(
65
+
module: Some("option"),
66
+
function: "unwrap",
67
+
arguments: [
68
+
stare.local_variable("option"),
69
+
stare.value(value.string("unwrapped")),
70
+
],
71
+
),
72
+
],
73
+
),
74
+
stare.function(
75
+
name: "main",
76
+
public: True,
77
+
parameters: [],
78
+
return_type: None,
79
+
statements: [
80
+
stare.function_call(module: None, function: "do_thing", arguments: [
81
+
stare.value(value.option(
82
+
qualified: False,
83
+
option: Some(value.string("")),
84
+
)),
85
+
]),
86
+
],
87
+
),
88
+
],
89
+
)
90
+
91
+
module
92
+
|> stare.generate()
93
+
|> stare.format()
94
+
|> assert_ok()
95
+
|> birdie.snap("Imported type")
96
+
}
97
+
12
98
pub fn integer_addition_test() {
13
99
let module =
14
100
stare.module(
···
124
210
name: "main",
125
211
public: True,
126
212
parameters: [],
127
-
return_type: Some(type_.nil()),
213
+
return_type: Some(type_.nil),
128
214
statements: [
129
215
stare.function_call(
130
216
module: Some("io"),