Skip to content

Commit 77f966f

Browse files
committed
[Lobster] optional scalars support
1 parent e86d5b8 commit 77f966f

File tree

7 files changed

+237
-6
lines changed

7 files changed

+237
-6
lines changed

lobster/flatbuffers.lobster

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,10 @@ class builder:
257257
f(x)
258258
Slot(o)
259259

260+
def PrependSlot(o:int, x, f):
261+
f(x)
262+
Slot(o)
263+
260264
def PrependBoolSlot(o, x, d): PrependSlot(o, x, d): PrependBool(_)
261265
def PrependByteSlot(o, x, d): PrependSlot(o, x, d): PrependByte(_)
262266
def PrependUint8Slot(o, x, d): PrependSlot(o, x, d): PrependUint8(_)
@@ -270,6 +274,19 @@ class builder:
270274
def PrependFloat32Slot(o, x, d): PrependSlot(o, x, d): PrependFloat32(_)
271275
def PrependFloat64Slot(o, x, d): PrependSlot(o, x, d): PrependFloat64(_)
272276

277+
def PrependBoolSlot(o, x): PrependSlot(o, x): PrependBool(_)
278+
def PrependByteSlot(o, x): PrependSlot(o, x): PrependByte(_)
279+
def PrependUint8Slot(o, x): PrependSlot(o, x): PrependUint8(_)
280+
def PrependUint16Slot(o, x): PrependSlot(o, x): PrependUint16(_)
281+
def PrependUint32Slot(o, x): PrependSlot(o, x): PrependUint32(_)
282+
def PrependUint64Slot(o, x): PrependSlot(o, x): PrependUint64(_)
283+
def PrependInt8Slot(o, x): PrependSlot(o, x): PrependInt8(_)
284+
def PrependInt16Slot(o, x): PrependSlot(o, x): PrependInt16(_)
285+
def PrependInt32Slot(o, x): PrependSlot(o, x): PrependInt32(_)
286+
def PrependInt64Slot(o, x): PrependSlot(o, x): PrependInt64(_)
287+
def PrependFloat32Slot(o, x): PrependSlot(o, x): PrependFloat32(_)
288+
def PrependFloat64Slot(o, x): PrependSlot(o, x): PrependFloat64(_)
289+
273290
def PrependUOffsetTRelativeSlot(o:int, x:offset):
274291
if x.o:
275292
PrependUOffsetTRelative(x)

src/idl_gen_lobster.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,14 @@ class LobsterGenerator : public BaseGenerator {
110110
offsets + ")";
111111

112112
} else {
113+
auto defval = field.nullable ? "0" : field.value.constant;
113114
acc = "buf_.flatbuffers_field_" + GenTypeName(field.value.type) +
114-
"(pos_, " + offsets + ", " + field.value.constant + ")";
115+
"(pos_, " + offsets + ", " + defval + ")";
115116
}
116117
if (field.value.type.enum_def)
117118
acc = NormalizedName(*field.value.type.enum_def) + "(" + acc + ")";
119+
if (field.nullable)
120+
acc += ", buf_.flatbuffers_field_present(pos_, " + offsets + ")";
118121
code += def + "():\n return " + acc + "\n";
119122
return;
120123
}
@@ -198,7 +201,7 @@ class LobsterGenerator : public BaseGenerator {
198201
NormalizedName(field) + ":" + LobsterType(field.value.type) +
199202
"):\n b_.Prepend" + GenMethod(field.value.type) + "Slot(" +
200203
NumToString(offset) + ", " + NormalizedName(field);
201-
if (IsScalar(field.value.type.base_type))
204+
if (IsScalar(field.value.type.base_type) && !field.nullable)
202205
code += ", " + field.value.constant;
203206
code += ")\n return this\n";
204207
}

src/idl_parser.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2258,7 +2258,8 @@ CheckedError Parser::CheckClash(std::vector<FieldDef *> &fields,
22582258

22592259

22602260
bool Parser::SupportsNullableScalars() const {
2261-
return !(opts.lang_to_generate & ~(IDLOptions::kRust | IDLOptions::kSwift));
2261+
return !(opts.lang_to_generate &
2262+
~(IDLOptions::kRust | IDLOptions::kSwift | IDLOptions::kLobster));
22622263
}
22632264

22642265
bool Parser::SupportsAdvancedUnionFeatures() const {

tests/generate_code.bat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ set TEST_NOINCL_FLAGS=%TEST_BASE_FLAGS% --no-includes --no-fb-import
5454
..\%buildtype%\flatc.exe --cpp %TEST_BASE_FLAGS% --cpp-ptr-type flatbuffers::unique_ptr native_type_test.fbs || goto FAIL
5555

5656
@rem Generate the optional scalar code for tests.
57-
..\%buildtype%\flatc.exe --rust optional_scalars.fbs || goto FAIL
57+
..\%buildtype%\flatc.exe --rust --lobster optional_scalars.fbs || goto FAIL
5858

5959
@rem Generate the schema evolution tests
6060
..\%buildtype%\flatc.exe --cpp --scoped-enums %TEST_CPP_FLAGS% -o evolution_test ./evolution_test/evolution_v1.fbs ./evolution_test/evolution_v2.fbs || goto FAIL

tests/generate_code.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ $TEST_NOINCL_FLAGS $TEST_CPP_FLAGS $TEST_CS_FLAGS -o namespace_test namespace_te
5252
../flatc --dart monster_extra.fbs
5353

5454
# Generate optional scalar code for tests.
55-
../flatc --rust optional_scalars.fbs
55+
../flatc --rust --lobster optional_scalars.fbs
5656

5757
# Generate the schema evolution tests
5858
../flatc --cpp --scoped-enums $TEST_CPP_FLAGS -o evolution_test ./evolution_test/evolution_v*.fbs

tests/lobstertest.lobster

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import from "../lobster/"
1616
import monster_test_generated
17+
import optional_scalars_generated
1718

1819
def check_read_buffer(buf):
1920
// CheckReadBuffer checks that the given buffer is evaluated correctly as the example Monster.
@@ -108,6 +109,28 @@ def make_monster_from_generated_code():
108109

109110
return b.SizedCopy()
110111

112+
def test_optional_scalars():
113+
def build(add_fields):
114+
let b = flatbuffers_builder {}
115+
let ss = optional_scalars_ScalarStuffBuilder { b }.start()
116+
if add_fields:
117+
ss.add_just_i8(1)
118+
ss.add_maybe_i8(1)
119+
ss.add_default_i8(1)
120+
b.Finish(ss.end())
121+
return optional_scalars_GetRootAsScalarStuff(b.SizedCopy())
122+
123+
var root = build(true)
124+
assert root.just_i8() == 1 and root.default_i8() == 1
125+
var maybe_val, maybe_present = root.maybe_i8()
126+
assert maybe_val == 1 and maybe_present == true
127+
128+
root = build(false)
129+
assert root.just_i8() == 0 and root.default_i8() == 42
130+
maybe_val, maybe_present = root.maybe_i8()
131+
assert maybe_val == 0 and maybe_present == false
132+
133+
111134
// Verify that the canonical flatbuffer file (produced by the C++ implementation)
112135
// is readable by the generated Lobster code.
113136
let fb2 = read_file("monsterdata_test.mon")
@@ -134,4 +157,7 @@ assert not err2
134157
// Check the resulting binary again (full roundtrip test):
135158
check_read_buffer(fb3)
136159

137-
print "Lobster test succesful!"
160+
// Additional tests.
161+
test_optional_scalars()
162+
163+
print "Lobster test succesful!"
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
// automatically generated by the FlatBuffers compiler, do not modify
2+
import flatbuffers
3+
4+
namespace optional_scalars
5+
6+
class ScalarStuff
7+
8+
class ScalarStuff : flatbuffers_handle
9+
def just_i8():
10+
return buf_.flatbuffers_field_int8(pos_, 4, 0)
11+
def maybe_i8():
12+
return buf_.flatbuffers_field_int8(pos_, 6, 0), buf_.flatbuffers_field_present(pos_, 6)
13+
def default_i8():
14+
return buf_.flatbuffers_field_int8(pos_, 8, 42)
15+
def just_u8():
16+
return buf_.flatbuffers_field_int8(pos_, 10, 0)
17+
def maybe_u8():
18+
return buf_.flatbuffers_field_int8(pos_, 12, 0), buf_.flatbuffers_field_present(pos_, 12)
19+
def default_u8():
20+
return buf_.flatbuffers_field_int8(pos_, 14, 42)
21+
def just_i16():
22+
return buf_.flatbuffers_field_int16(pos_, 16, 0)
23+
def maybe_i16():
24+
return buf_.flatbuffers_field_int16(pos_, 18, 0), buf_.flatbuffers_field_present(pos_, 18)
25+
def default_i16():
26+
return buf_.flatbuffers_field_int16(pos_, 20, 42)
27+
def just_u16():
28+
return buf_.flatbuffers_field_int16(pos_, 22, 0)
29+
def maybe_u16():
30+
return buf_.flatbuffers_field_int16(pos_, 24, 0), buf_.flatbuffers_field_present(pos_, 24)
31+
def default_u16():
32+
return buf_.flatbuffers_field_int16(pos_, 26, 42)
33+
def just_i32():
34+
return buf_.flatbuffers_field_int32(pos_, 28, 0)
35+
def maybe_i32():
36+
return buf_.flatbuffers_field_int32(pos_, 30, 0), buf_.flatbuffers_field_present(pos_, 30)
37+
def default_i32():
38+
return buf_.flatbuffers_field_int32(pos_, 32, 42)
39+
def just_u32():
40+
return buf_.flatbuffers_field_int32(pos_, 34, 0)
41+
def maybe_u32():
42+
return buf_.flatbuffers_field_int32(pos_, 36, 0), buf_.flatbuffers_field_present(pos_, 36)
43+
def default_u32():
44+
return buf_.flatbuffers_field_int32(pos_, 38, 42)
45+
def just_i64():
46+
return buf_.flatbuffers_field_int64(pos_, 40, 0)
47+
def maybe_i64():
48+
return buf_.flatbuffers_field_int64(pos_, 42, 0), buf_.flatbuffers_field_present(pos_, 42)
49+
def default_i64():
50+
return buf_.flatbuffers_field_int64(pos_, 44, 42)
51+
def just_u64():
52+
return buf_.flatbuffers_field_int64(pos_, 46, 0)
53+
def maybe_u64():
54+
return buf_.flatbuffers_field_int64(pos_, 48, 0), buf_.flatbuffers_field_present(pos_, 48)
55+
def default_u64():
56+
return buf_.flatbuffers_field_int64(pos_, 50, 42)
57+
def just_f32():
58+
return buf_.flatbuffers_field_float32(pos_, 52, 0.0)
59+
def maybe_f32():
60+
return buf_.flatbuffers_field_float32(pos_, 54, 0), buf_.flatbuffers_field_present(pos_, 54)
61+
def default_f32():
62+
return buf_.flatbuffers_field_float32(pos_, 56, 42.0)
63+
def just_f64():
64+
return buf_.flatbuffers_field_float64(pos_, 58, 0.0)
65+
def maybe_f64():
66+
return buf_.flatbuffers_field_float64(pos_, 60, 0), buf_.flatbuffers_field_present(pos_, 60)
67+
def default_f64():
68+
return buf_.flatbuffers_field_float64(pos_, 62, 42.0)
69+
def just_bool():
70+
return buf_.flatbuffers_field_int8(pos_, 64, 0)
71+
def maybe_bool():
72+
return buf_.flatbuffers_field_int8(pos_, 66, 0), buf_.flatbuffers_field_present(pos_, 66)
73+
def default_bool():
74+
return buf_.flatbuffers_field_int8(pos_, 68, 1)
75+
76+
def GetRootAsScalarStuff(buf:string): return ScalarStuff { buf, buf.flatbuffers_indirect(0) }
77+
78+
struct ScalarStuffBuilder:
79+
b_:flatbuffers_builder
80+
def start():
81+
b_.StartObject(33)
82+
return this
83+
def add_just_i8(just_i8:int):
84+
b_.PrependInt8Slot(0, just_i8, 0)
85+
return this
86+
def add_maybe_i8(maybe_i8:int):
87+
b_.PrependInt8Slot(1, maybe_i8)
88+
return this
89+
def add_default_i8(default_i8:int):
90+
b_.PrependInt8Slot(2, default_i8, 42)
91+
return this
92+
def add_just_u8(just_u8:int):
93+
b_.PrependUint8Slot(3, just_u8, 0)
94+
return this
95+
def add_maybe_u8(maybe_u8:int):
96+
b_.PrependUint8Slot(4, maybe_u8)
97+
return this
98+
def add_default_u8(default_u8:int):
99+
b_.PrependUint8Slot(5, default_u8, 42)
100+
return this
101+
def add_just_i16(just_i16:int):
102+
b_.PrependInt16Slot(6, just_i16, 0)
103+
return this
104+
def add_maybe_i16(maybe_i16:int):
105+
b_.PrependInt16Slot(7, maybe_i16)
106+
return this
107+
def add_default_i16(default_i16:int):
108+
b_.PrependInt16Slot(8, default_i16, 42)
109+
return this
110+
def add_just_u16(just_u16:int):
111+
b_.PrependUint16Slot(9, just_u16, 0)
112+
return this
113+
def add_maybe_u16(maybe_u16:int):
114+
b_.PrependUint16Slot(10, maybe_u16)
115+
return this
116+
def add_default_u16(default_u16:int):
117+
b_.PrependUint16Slot(11, default_u16, 42)
118+
return this
119+
def add_just_i32(just_i32:int):
120+
b_.PrependInt32Slot(12, just_i32, 0)
121+
return this
122+
def add_maybe_i32(maybe_i32:int):
123+
b_.PrependInt32Slot(13, maybe_i32)
124+
return this
125+
def add_default_i32(default_i32:int):
126+
b_.PrependInt32Slot(14, default_i32, 42)
127+
return this
128+
def add_just_u32(just_u32:int):
129+
b_.PrependUint32Slot(15, just_u32, 0)
130+
return this
131+
def add_maybe_u32(maybe_u32:int):
132+
b_.PrependUint32Slot(16, maybe_u32)
133+
return this
134+
def add_default_u32(default_u32:int):
135+
b_.PrependUint32Slot(17, default_u32, 42)
136+
return this
137+
def add_just_i64(just_i64:int):
138+
b_.PrependInt64Slot(18, just_i64, 0)
139+
return this
140+
def add_maybe_i64(maybe_i64:int):
141+
b_.PrependInt64Slot(19, maybe_i64)
142+
return this
143+
def add_default_i64(default_i64:int):
144+
b_.PrependInt64Slot(20, default_i64, 42)
145+
return this
146+
def add_just_u64(just_u64:int):
147+
b_.PrependUint64Slot(21, just_u64, 0)
148+
return this
149+
def add_maybe_u64(maybe_u64:int):
150+
b_.PrependUint64Slot(22, maybe_u64)
151+
return this
152+
def add_default_u64(default_u64:int):
153+
b_.PrependUint64Slot(23, default_u64, 42)
154+
return this
155+
def add_just_f32(just_f32:float):
156+
b_.PrependFloat32Slot(24, just_f32, 0.0)
157+
return this
158+
def add_maybe_f32(maybe_f32:float):
159+
b_.PrependFloat32Slot(25, maybe_f32)
160+
return this
161+
def add_default_f32(default_f32:float):
162+
b_.PrependFloat32Slot(26, default_f32, 42.0)
163+
return this
164+
def add_just_f64(just_f64:float):
165+
b_.PrependFloat64Slot(27, just_f64, 0.0)
166+
return this
167+
def add_maybe_f64(maybe_f64:float):
168+
b_.PrependFloat64Slot(28, maybe_f64)
169+
return this
170+
def add_default_f64(default_f64:float):
171+
b_.PrependFloat64Slot(29, default_f64, 42.0)
172+
return this
173+
def add_just_bool(just_bool:int):
174+
b_.PrependBoolSlot(30, just_bool, 0)
175+
return this
176+
def add_maybe_bool(maybe_bool:int):
177+
b_.PrependBoolSlot(31, maybe_bool)
178+
return this
179+
def add_default_bool(default_bool:int):
180+
b_.PrependBoolSlot(32, default_bool, 1)
181+
return this
182+
def end():
183+
return b_.EndObject()
184+

0 commit comments

Comments
 (0)