Skip to content

Commit c110443

Browse files
committed
Add support for untyped variables having an assignment expression
1 parent d725a2f commit c110443

File tree

7 files changed

+83
-37
lines changed

7 files changed

+83
-37
lines changed

include/JellyCore/ASTNodes.h

+2
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ enum _ASTFlags {
7373
ASTFlagsIsPointerArithmetic = 1 << 7,
7474
ASTFlagsCallIsInitialization = 1 << 8,
7575
ASTFlagsArrayTypeIsStatic = 1 << 9,
76+
ASTFlagsIsUntyped = 1 << 10,
7677
};
7778
typedef enum _ASTFlags ASTFlags;
7879

@@ -143,6 +144,7 @@ struct _ASTNode {
143144
};
144145

145146
#define ASTNodeGetType(__NODE__) (((ASTNodeRef)__NODE__)->type)
147+
#define ASTNodeHasFlag(__NODE__, __FLAG__) (((ASTNodeRef)__NODE__)->flags & __FLAG__)
146148

147149
struct _ASTExpression {
148150
struct _ASTNode base;

lib/JellyCore/ASTContext.c

+6-1
Original file line numberDiff line numberDiff line change
@@ -618,7 +618,6 @@ ASTInitializerDeclarationRef ASTContextCreateInitializerDeclaration(ASTContextRe
618618

619619
ASTValueDeclarationRef ASTContextCreateValueDeclaration(ASTContextRef context, SourceRange location, ScopeID scope, ASTValueKind kind,
620620
StringRef name, ASTTypeRef type, ASTExpressionRef initializer) {
621-
assert(name && type);
622621
assert((kind == ASTValueKindParameter && !initializer) || (kind == ASTValueKindVariable || kind == ASTValueKindEnumerationElement));
623622

624623
ASTValueDeclarationRef node = (ASTValueDeclarationRef)_ASTContextCreateNode(context, ASTTagValueDeclaration, location, scope);
@@ -627,6 +626,12 @@ ASTValueDeclarationRef ASTContextCreateValueDeclaration(ASTContextRef context, S
627626
node->kind = kind;
628627
ASTNodeGetType(node) = type;
629628
node->initializer = initializer;
629+
630+
if (!type) {
631+
ASTNodeGetType(node) = (ASTTypeRef)ASTContextGetBuiltinType(context, ASTBuiltinTypeKindError);
632+
node->base.base.flags |= ASTFlagsIsUntyped;
633+
}
634+
630635
return node;
631636
}
632637

lib/JellyCore/ASTSubstitution.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,10 @@ static inline void _ASTApplySubstitution(ASTContextRef context, ASTNodeRef node)
220220

221221
if (node->tag == ASTTagValueDeclaration) {
222222
ASTValueDeclarationRef declaration = (ASTValueDeclarationRef)node;
223-
_ASTApplySubstitutionInplace(context, declaration->base.base.type, ASTTypeRef);
223+
if (ASTNodeGetType(declaration)) {
224+
_ASTApplySubstitutionInplace(context, ASTNodeGetType(declaration), ASTTypeRef);
225+
}
226+
224227
if (declaration->initializer) {
225228
_ASTApplySubstitutionInplace(context, declaration->initializer, ASTExpressionRef);
226229
}

lib/JellyCore/NameResolution.c

+36-22
Original file line numberDiff line numberDiff line change
@@ -110,40 +110,46 @@ void PerformNameResolution(ASTContextRef context, ASTModuleDeclarationRef module
110110
}
111111
}
112112

113-
for (Index index = 0; index < ASTArrayGetElementCount(module->sourceUnits); index++)
114-
{
113+
for (Index index = 0; index < ASTArrayGetElementCount(module->sourceUnits); index++) {
115114
ASTSourceUnitRef sourceUnit = (ASTSourceUnitRef)ASTArrayGetElementAtIndex(module->sourceUnits, index);
116-
for (Index sourceUnitIndex = 0; sourceUnitIndex < ASTArrayGetElementCount(sourceUnit->declarations); sourceUnitIndex++)
117-
{
115+
for (Index sourceUnitIndex = 0; sourceUnitIndex < ASTArrayGetElementCount(sourceUnit->declarations); sourceUnitIndex++) {
118116
ASTNodeRef child = (ASTNodeRef)ASTArrayGetElementAtIndex(sourceUnit->declarations, sourceUnitIndex);
119-
if (child->tag == ASTTagEnumerationDeclaration)
120-
{
117+
if (child->tag == ASTTagEnumerationDeclaration) {
121118
ASTEnumerationDeclarationRef enumeration = (ASTEnumerationDeclarationRef)child;
122119
_PerformNameResolutionForEnumerationBody(context, enumeration);
123120
continue;
124121
}
125122

126-
if (child->tag == ASTTagStructureDeclaration)
127-
{
123+
if (child->tag == ASTTagStructureDeclaration) {
128124
ASTStructureDeclarationRef structure = (ASTStructureDeclarationRef)child;
129125
_PerformNameResolutionForStructureBody(context, structure);
130126
continue;
131127
}
132128

133-
if (child->tag == ASTTagValueDeclaration)
134-
{
129+
if (child->tag == ASTTagValueDeclaration) {
135130
ASTValueDeclarationRef value = (ASTValueDeclarationRef)child;
131+
ASTTypeRef Type = ASTNodeGetType(value);
132+
Bool IsUntyped = ASTTypeIsError(Type) && ASTNodeHasFlag(value, ASTFlagsIsUntyped);
133+
134+
if (IsUntyped && !value->initializer) {
135+
ReportError("Cannot infer type of declaration");
136+
continue;
137+
}
138+
139+
if (IsUntyped && value->initializer) {
140+
_PerformNameResolutionForExpression(context, value->initializer, true);
141+
ASTNodeGetType(value) = ASTNodeGetType(value->initializer);
142+
}
143+
136144
_ResolveDeclarationsOfTypeAndSubstituteType(context, value->base.base.scope, &value->base.base.type);
137145

138-
if (value->initializer)
139-
{
146+
if (value->initializer) {
140147
value->initializer->expectedType = value->base.base.type;
141148
_PerformNameResolutionForExpression(context, value->initializer, true);
142149
}
143150
}
144151

145-
if (child->tag == ASTTagTypeAliasDeclaration)
146-
{
152+
if (child->tag == ASTTagTypeAliasDeclaration) {
147153
ASTTypeAliasDeclarationRef alias = (ASTTypeAliasDeclarationRef)child;
148154
_ResolveDeclarationsOfTypeAndSubstituteType(context, alias->base.base.scope, &alias->base.base.type);
149155
}
@@ -571,22 +577,30 @@ static inline void _PerformNameResolutionForNode(ASTContextRef context, ASTNodeR
571577
ASTValueDeclarationRef value = (ASTValueDeclarationRef)node;
572578
assert(value->kind == ASTValueKindVariable);
573579

574-
if (_ResolveDeclarationsOfTypeAndSubstituteType(context, value->base.base.scope, &value->base.base.type))
575-
{
580+
ASTTypeRef Type = ASTNodeGetType(value);
581+
Bool IsUntyped = ASTTypeIsError(Type) && ASTNodeHasFlag(value, ASTFlagsIsUntyped);
582+
if (IsUntyped && !value->initializer) {
583+
ReportError("Cannot infer type of declaration");
584+
break;
585+
}
586+
587+
if (IsUntyped && value->initializer) {
588+
_PerformNameResolutionForExpression(context, value->initializer, true);
589+
ASTNodeGetType(value) = ASTNodeGetType(value->initializer);
590+
}
591+
592+
if (_ResolveDeclarationsOfTypeAndSubstituteType(context, value->base.base.scope, &value->base.base.type)) {
576593
SymbolID symbol = SymbolTableLookupSymbol(symbolTable, value->base.base.scope, value->base.name);
577-
if (symbol == kSymbolNull)
578-
{
594+
if (symbol == kSymbolNull) {
579595
symbol = SymbolTableInsertSymbol(symbolTable, value->base.base.scope, value->base.name);
580596
SymbolTableSetSymbolDefinition(symbolTable, symbol, value);
581597
}
582-
else
583-
{
598+
else {
584599
ReportError("Invalid redeclaration of identifier");
585600
}
586601
}
587602

588-
if (value->initializer)
589-
{
603+
if (value->initializer) {
590604
value->initializer->expectedType = value->base.base.type;
591605
_PerformNameResolutionForExpression(context, value->initializer, true);
592606
}

lib/JellyCore/Parser.c

+13-12
Original file line numberDiff line numberDiff line change
@@ -1783,7 +1783,7 @@ static inline ASTInitializerDeclarationRef _ParserParseInitializerDeclaration(Pa
17831783
return declaration;
17841784
}
17851785

1786-
/// grammar: variable-declaration := "var" identifier ":" type-identifier [ "=" expression ]
1786+
/// grammar: variable-declaration := "var" identifier [ ":" type-identifier [ "=" expression ] ] | "=" expression
17871787
static inline ASTValueDeclarationRef _ParserParseVariableDeclaration(ParserRef parser) {
17881788
SourceRange location = parser->token.location;
17891789

@@ -1798,17 +1798,15 @@ static inline ASTValueDeclarationRef _ParserParseVariableDeclaration(ParserRef p
17981798
return NULL;
17991799
}
18001800

1801-
if (!_ParserConsumeToken(parser, TokenKindColon)) {
1802-
ReportError("Expected ':' after name of variable declaration");
1803-
return NULL;
1804-
}
1805-
1806-
ASTTypeRef type = _ParserParseType(parser);
1807-
if (!type) {
1808-
ReportError("Expected type of variable declaration");
1809-
return NULL;
1801+
ASTTypeRef type = NULL;
1802+
if (_ParserConsumeToken(parser, TokenKindColon)) {
1803+
type = _ParserParseType(parser);
1804+
if (!type) {
1805+
ReportError("Expected type of variable declaration");
1806+
return NULL;
1807+
}
18101808
}
1811-
1809+
18121810
ASTExpressionRef initializer = NULL;
18131811
ASTBinaryOperator binary = _ParserConsumeBinaryOperator(parser);
18141812
if (binary == ASTBinaryOperatorAssign) {
@@ -1817,9 +1815,12 @@ static inline ASTValueDeclarationRef _ParserParseVariableDeclaration(ParserRef p
18171815
ReportError("Expected expression");
18181816
return NULL;
18191817
}
1820-
} else if (binary != ASTBinaryOperatorUnknown) {
1818+
} else if (type && binary != ASTBinaryOperatorUnknown) {
18211819
ReportError("Unexpected binary operator found!");
18221820
return NULL;
1821+
} else if (!type) {
1822+
ReportError("Expected type declaration or assignment expression of variable declaration");
1823+
return NULL;
18231824
}
18241825

18251826
location.end = parser->token.location.start;
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
var x Int // expect-error: Expected ':' after name of variable declaration
1+
var x Int // expect-error: Expected type declaration or assignment expression of variable declaration
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
var globalInt = 1
2+
var globalFloat = 1.0
3+
var globalString = "Hello Global!"
4+
5+
func resolve_from_func() -> Int {
6+
return 1
7+
}
8+
9+
func main() -> Void {
10+
var x = 1
11+
var y = "Hello World!"
12+
var z = x
13+
var w = resolve_from_func()
14+
15+
call(x)
16+
call(y)
17+
call(w)
18+
}
19+
20+
func call(x: Int) -> Void {}
21+
func call(y: String) -> Void {}

0 commit comments

Comments
 (0)