Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(type_inference): added NumericDefaultInt cons #3252

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions compiler/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,11 @@ func compile(n semantic.Node, subst map[uint64]semantic.MonoType, scope Scope) (
return &integerEvaluator{
i: n.Value,
}, nil
case *semantic.PolyNumericLiteral:
return &integerEvaluator{
i: n.Value,
}, nil

case *semantic.UnsignedIntegerLiteral:
return &unsignedIntegerEvaluator{
i: n.Value,
Expand Down
5 changes: 5 additions & 0 deletions docs/SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,11 @@ Int, Uint, and Float types are Divisible.

Int, Uint, and Float types are Numeric.

##### Numeric Default Int Constraint

Integer literals are polymorphic and can be interpreted as Int, Uint, or Float types.
This constraint is used to infer the type of integer literals based on the context of the program.

##### Comparable Constraint

Comparable types are those the binary comparison operators `<`, `<=`, `>`, or `>=` accept.
Expand Down
8 changes: 8 additions & 0 deletions internal/fbsemantic/semantic.fbs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ enum Kind : ubyte {
Record,
Negatable,
Timeable,
NumericDefaultInt,
}

table Constraint {
Expand Down Expand Up @@ -133,6 +134,7 @@ union Expression {
DateTimeLiteral,
DurationLiteral,
FloatLiteral,
PolyNumericLiteral,
IntegerLiteral,
StringLiteral,
RegexpLiteral,
Expand Down Expand Up @@ -397,6 +399,12 @@ table DurationLiteral {
value:[Duration];
}

table PolyNumericLiteral {
loc:SourceLocation;
value:int64;
typ:MonoType;
}

table IntegerLiteral {
loc:SourceLocation;
value:int64;
Expand Down
137 changes: 113 additions & 24 deletions internal/fbsemantic/semantic_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions interpreter/interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ func (itrp *Interpreter) doLiteral(lit semantic.Literal) (values.Value, error) {
return values.NewDuration(dur), nil
case *semantic.FloatLiteral:
return values.NewFloat(l.Value), nil
case *semantic.IntegerLiteral:
case *semantic.PolyNumericLiteral:
return values.NewInt(l.Value), nil
case *semantic.UnsignedIntegerLiteral:
return values.NewUInt(l.Value), nil
Expand Down Expand Up @@ -1140,7 +1140,7 @@ func resolveValue(v values.Value) (semantic.Node, bool, error) {
Value: v.Str(),
}, true, nil
case semantic.Int:
return &semantic.IntegerLiteral{
return &semantic.PolyNumericLiteral{
Value: v.Int(),
}, true, nil
case semantic.UInt:
Expand Down
46 changes: 23 additions & 23 deletions interpreter/interpreter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,14 @@ func TestEval(t *testing.T) {
{
name: "string interpolation missing field",
query: `
r = makeRecord(o: {a: "foo", b: 42})
r = o: {a: "foo", b: 42}
"r._value = ${r._value}"`,
wantErr: any,
},
{
name: "string interpolation field has wrong type",
query: `
r = makeRecord(o: {a: "foo", b: 42})
r = o: {a: "foo", b: 42}
"r._value = ${r.b}"`,
wantErr: any,
},
Expand Down Expand Up @@ -287,7 +287,7 @@ func TestEval(t *testing.T) {
name: "array index expression out of bounds high",
query: `
a = [1, 2, 3]
i = 3
i = 3
x = a[i]
`,
wantErr: any,
Expand Down Expand Up @@ -439,31 +439,31 @@ func TestEval_Operator_Precedence(t *testing.T) {
want values.Value
}{
{
src: "2.0 * 3.0 ^ 2.0",
src: "2 * 3 ^ 2",
want: values.NewFloat(18.0),
},
{
src: "(2.0 * 3.0) ^ 2.0",
src: "(2 * 3) ^ 2",
want: values.NewFloat(36.0),
},
{
src: "4.0 / 2.0 ^ 2.0",
src: "4 / 2 ^ 2",
want: values.NewFloat(1.0),
},
{
src: "(4.0 / 2.0) ^ 2.0",
src: "(4 / 2) ^ 2",
want: values.NewFloat(4.0),
},
{
src: "2.0 % 4.0 ^ 2.0",
src: "2 % 4 ^ 2",
want: values.NewFloat(2.0),
},
{
src: "(2.0 % 4.0) ^ 2.0",
src: "(2 % 4) ^ 2",
want: values.NewFloat(4.0),
},
{
src: "1.0 + 2.0 * 3.0",
src: "1 + 2 * 3.0",
want: values.NewFloat(7.0),
},
{
Expand Down Expand Up @@ -503,35 +503,35 @@ func TestEval_Operator_Precedence(t *testing.T) {
want: values.NewFloat(6.0),
},
{
src: "1.0 + 2.0 < 4.0",
src: "1 + 2 < 4",
want: values.NewBool(true),
},
{
src: "(1.0 + 2.0) < 4.0",
src: "(1 + 2) < 4",
want: values.NewBool(true),
},
{
src: "1.0 + 2.0 <= 4.0",
src: "1 + 2 <= 4",
want: values.NewBool(true),
},
{
src: "(1.0 + 2.0) <= 4.0",
src: "(1 + 2) <= 4",
want: values.NewBool(true),
},
{
src: "1.0 + 2.0 > 4.0",
src: "1 + 2 > 4",
want: values.NewBool(false),
},
{
src: "(1.0 + 2.0) > 4.0",
src: "(1 + 2) > 4",
want: values.NewBool(false),
},
{
src: "1.0 + 2.0 >= 4.0",
src: "1 + 2 >= 4",
want: values.NewBool(false),
},
{
src: "(1.0 + 2.0) >= 4.0",
src: "(1 + 2) >= 4",
want: values.NewBool(false),
},
{
Expand Down Expand Up @@ -666,9 +666,9 @@ func TestInterpreter_MultipleEval(t *testing.T) {
Value: values.NewInt(2),
Node: &semantic.ExpressionStatement{
Expression: &semantic.BinaryExpression{
Left: &semantic.IntegerLiteral{Value: 1},
Left: &semantic.PolyNumericLiteral{Value: 1},
Operator: ast.AdditionOperator,
Right: &semantic.IntegerLiteral{Value: 1},
Right: &semantic.PolyNumericLiteral{Value: 1},
},
},
},
Expand All @@ -686,9 +686,9 @@ func TestInterpreter_MultipleEval(t *testing.T) {
Value: values.NewInt(2),
Node: &semantic.ExpressionStatement{
Expression: &semantic.BinaryExpression{
Left: &semantic.IntegerLiteral{Value: 1},
Left: &semantic.PolyNumericLiteral{Value: 1},
Operator: ast.AdditionOperator,
Right: &semantic.IntegerLiteral{Value: 1},
Right: &semantic.PolyNumericLiteral{Value: 1},
},
},
},
Expand All @@ -709,7 +709,7 @@ func TestInterpreter_MultipleEval(t *testing.T) {
Property: "yield",
},
Arguments: &semantic.ObjectExpression{Properties: []*semantic.Property{}},
Pipe: &semantic.IntegerLiteral{Value: 0},
Pipe: &semantic.PolyNumericLiteral{Value: 0},
},
},
{
Expand Down
4 changes: 2 additions & 2 deletions libflux/c/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ void test_semantic() {

{
printf("Parsing to AST\n");
struct flux_ast_pkg_t *ast_pkg_foo = flux_parse("test", "package foo\nx = 1 + 1.0");
struct flux_ast_pkg_t *ast_pkg_foo = flux_parse("test", "package foo\nx = 1 + \"1.0\"");
assert(ast_pkg_foo != NULL);

printf("Analyzing (expect failure)\n");
Expand Down Expand Up @@ -115,7 +115,7 @@ void test_semantic() {

{
printf("Parsing to AST\n");
struct flux_ast_pkg_t *ast_pkg_foo = flux_parse("test", "package foo\nx = 1 + 1.0");
struct flux_ast_pkg_t *ast_pkg_foo = flux_parse("test", "package foo\nx = 1 + \"1.0\"");
assert(ast_pkg_foo != NULL);
printf("Find variable type v (expect failure)\n");
struct flux_buffer_t buf;
Expand Down
Loading