Skip to content

Commit 397846e

Browse files
committed
Modify LoxLexer/LoxParser.g4 grammer, extends parser to handle return type declaration, minor update to native.c and resolver.c, add new test file type.lox.
1 parent ca47149 commit 397846e

6 files changed

Lines changed: 64 additions & 25 deletions

File tree

grammar/LoxLexer.g4

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
lexer grammar Lox;
22

33
SEPARATOR: [ \t\r\n];
4-
KEYWORD: AND | AS | ASYNC | AWAIT | BREAK | CATCH | CLASS | CONTINUE | DEFAULT | ELSE | FINALLY | FOR | FUN | IF | OR | RETURN | SUPER | THROW| TRAIT | TRY | VAL | VAR | WHILE | WITH | YIELD;
4+
KEYWORD: AND | AS | ASYNC | AWAIT | BREAK | CATCH | CLASS | CONTINUE | DEFAULT | ELSE | EXTENDS | FINALLY | FOR | FUN | IF | OR | RETURN | SUPER | THROW| TRAIT | TRY | VAL | VAR | WHILE | WITH | YIELD;
55
AND: 'and';
66
AS: 'as';
77
ASYNC: 'async';
@@ -13,6 +13,7 @@ CLASS: 'class';
1313
CONTINUE: 'continue';
1414
DEFAULT: 'default';
1515
ELSE: 'else';
16+
EXTENDS: 'extends';
1617
FINALLY: 'finally';
1718
FOR: 'for';
1819
FUN: 'fun';

grammar/LoxParser.g4

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ call: primary (LPAREN arguments? RPAREN | LSQUARE expression QUESTION? RSQUARE |
4040
primary: 'nil' | 'true' | 'false' | INT | FLOAT | STRING | IDENTIFIER | (LPAREN expression RPAREN) | (LSQUARE arguments? RSQUARE) | (expression DOTDOT expression) | (CLASS classBody) | (FUN functionBody) | (SUPER DOT IDENTIFIER) | (TRAIT traitBody);
4141

4242
classBody: (LT IDENTIFIER)? (WITH parameters)? LBRACE function* RBRACE;
43-
function: ASYNC? CLASS? IDENTIFIER functionBody;
43+
function: ASYNC? CLASS? IDENTIFIER? IDENTIFIER functionBody;
4444
functionBody: LPAREN parameters? RPAREN block;
4545
traitBody: (WITH parameters)? LBRACE CLASS? function* RBRACE;
46-
parameters: (VAR? IDENTIFIER (VAR? COMMA IDENTIFIER)*) | (DOTDOT IDENTIFIER);
46+
parameters: (VAR? IDENTIFIER? IDENTIFIER (VAR? COMMA IDENTIFIER IDENTIFIER)*) | (DOTDOT IDENTIFIER IDENTIFIER);
4747
arguments: expression (COMMA expression)*;

src/compiler/parser.c

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1094,11 +1094,19 @@ static Ast* classDeclaration(Parser* parser) {
10941094
return newAst(AST_DECL_CLASS, name, 1, _class);
10951095
}
10961096

1097-
static Ast* funDeclaration(Parser* parser, bool isAsync) {
1097+
static Ast* funDeclaration(Parser* parser, bool isAsync, bool hasReturnType) {
1098+
Ast* returnType = NULL;
1099+
if (hasReturnType) {
1100+
advance(parser);
1101+
returnType = variable(parser, parser->previous, false);
1102+
}
10981103
consume(parser, TOKEN_IDENTIFIER, "Expect function name.");
10991104
Token name = parser->previous;
11001105
Ast* body = function(parser, isAsync, false);
1101-
return newAst(AST_DECL_FUN, name, 1, body);
1106+
1107+
Ast* ast = newAst(AST_DECL_FUN, name, 1, body);
1108+
if (returnType != NULL) astAppendChild(ast, returnType);
1109+
return ast;
11021110
}
11031111

11041112
static Ast* namespaceDeclaration(Parser* parser) {
@@ -1146,15 +1154,22 @@ static Ast* declaration(Parser* parser) {
11461154
if (check(parser, TOKEN_ASYNC) && checkNext(parser, TOKEN_FUN)) {
11471155
advance(parser);
11481156
advance(parser);
1149-
return funDeclaration(parser, true);
1157+
return funDeclaration(parser, true, false);
1158+
}
1159+
if (check(parser, TOKEN_ASYNC) && checkNext(parser, TOKEN_IDENTIFIER)) {
1160+
advance(parser);
1161+
return funDeclaration(parser, true, true);
11501162
}
11511163
else if (check(parser, TOKEN_CLASS) && checkNext(parser, TOKEN_IDENTIFIER)) {
11521164
advance(parser);
11531165
return classDeclaration(parser);
11541166
}
1155-
else if (check(parser, TOKEN_FUN) && checkNext(parser, TOKEN_IDENTIFIER)) {
1167+
else if ((check(parser, TOKEN_FUN) && checkNext(parser, TOKEN_IDENTIFIER))) {
11561168
advance(parser);
1157-
return funDeclaration(parser, false);
1169+
return funDeclaration(parser, false, false);
1170+
}
1171+
else if ((check(parser, TOKEN_IDENTIFIER) && checkNext(parser, TOKEN_IDENTIFIER))) {
1172+
return funDeclaration(parser, false, true);
11581173
}
11591174
else if (match(parser, TOKEN_NAMESPACE)) {
11601175
return namespaceDeclaration(parser);

src/compiler/resolver.c

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,23 @@ static ObjString* getSymbolFullName(Resolver* resolver, Token token) {
171171
return takeString(resolver->vm, fullName, length);
172172
}
173173

174+
static TypeInfo* getTypeForSymbol(Resolver* resolver, Token token) {
175+
ObjString* shortName = copyString(resolver->vm, token.start, token.length);
176+
TypeInfo* type = typeTableGet(resolver->vm->typetab, shortName);
177+
ObjString* fullName = NULL;
178+
179+
if (type == NULL) {
180+
fullName = concatenateString(resolver->vm, resolver->currentNamespace, shortName, ".");
181+
type = typeTableGet(resolver->vm->typetab, fullName);
182+
183+
if (type == NULL) {
184+
fullName = concatenateString(resolver->vm, resolver->vm->langNamespace->fullName, shortName, ".");
185+
type = typeTableGet(resolver->vm->typetab, fullName);
186+
}
187+
}
188+
return type;
189+
}
190+
174191
static bool findSymbol(Resolver* resolver, Token token) {
175192
ObjString* symbol = createSymbol(resolver, token);
176193
SymbolItem* item = symbolTableGet(resolver->currentSymtab, symbol);
@@ -246,10 +263,6 @@ static bool isTopLevel(Resolver* resolver) {
246263
return (resolver->currentFunction->enclosing == NULL);
247264
}
248265

249-
static bool isFunctionScope(SymbolScope scope) {
250-
return (scope == SYMBOL_SCOPE_FUNCTION || scope == SYMBOL_SCOPE_METHOD);
251-
}
252-
253266
static SymbolScope getFunctionScope(Ast* ast) {
254267
return (ast->kind == AST_DECL_METHOD) ? SYMBOL_SCOPE_METHOD : SYMBOL_SCOPE_FUNCTION;
255268
}
@@ -471,6 +484,16 @@ static void deriveAstTypeFromBinary(Resolver* resolver, Ast* ast, SymbolItem* it
471484
}
472485
}
473486

487+
static void deriveAstTypeForParam(Resolver* resolver, Ast* ast) {
488+
Ast* child = astGetChild(ast, 0);
489+
resolveChild(resolver, ast, 0);
490+
if (child->modifier.isQualified) {
491+
ObjString* typeName = createQualifiedSymbol(resolver, child);
492+
ast->type = typeTableGet(resolver->vm->typetab, typeName);
493+
}
494+
else ast->type = getTypeForSymbol(resolver, child->token);
495+
}
496+
474497
static SymbolItem* getVariable(Resolver* resolver, Ast* ast) {
475498
ObjString* symbol = createSymbol(resolver, ast->token);
476499
SymbolItem* item = findLocal(resolver, ast);
@@ -702,6 +725,10 @@ static void resolveOr(Resolver* resolver, Ast* ast) {
702725
static void resolveParam(Resolver* resolver, Ast* ast) {
703726
SymbolItem* item = declareVariable(resolver, ast, ast->modifier.isMutable);
704727
item->state = SYMBOL_STATE_DEFINED;
728+
if (astNumChild(ast) > 0) {
729+
deriveAstTypeForParam(resolver, ast);
730+
item->type = ast->type;
731+
}
705732
}
706733

707734
static void resolvePropertyGet(Resolver* resolver, Ast* ast) {

src/vm/native.c

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -208,31 +208,20 @@ ObjClass* getNativeClass(VM* vm, const char* fullName) {
208208
return AS_CLASS(klass);
209209
}
210210

211-
static ObjString* getNativeFullName(VM* vm, ObjString* namespaceName, ObjString* shortName) {
212-
size_t totalLength = (size_t)namespaceName->length + (size_t)shortName->length + 1;
213-
char* chars = bufferNewCString(totalLength);
214-
memcpy(chars, namespaceName->chars, namespaceName->length);
215-
chars[vm->langNamespace->fullName->length] = '.';
216-
memcpy(chars + namespaceName->length + 1, shortName->chars, shortName->length);
217-
chars[totalLength] = '\0';
218-
return takeString(vm, chars, (int)totalLength);
219-
}
220-
221211
TypeInfo* getNativeType(VM* vm, const char* name) {
222212
if (name == NULL) return NULL;
223213
ObjString* shortName = newString(vm, name);
224214
ObjString* fullName = NULL;
225215
TypeInfo* type = typeTableGet(vm->typetab, shortName);
226216

227217
if (type == NULL) {
228-
fullName = getNativeFullName(vm, vm->currentNamespace->fullName, shortName);
218+
fullName = concatenateString(vm, vm->currentNamespace->fullName, shortName, ".");
229219
type = typeTableGet(vm->typetab, fullName);
230220

231221
if (type == NULL) {
232-
fullName = getNativeFullName(vm, vm->langNamespace->fullName, shortName);
222+
fullName = concatenateString(vm, vm->langNamespace->fullName, shortName, ".");
233223
type = typeTableGet(vm->typetab, fullName);
234224

235-
236225
if (type == NULL) {
237226
runtimeError(vm, "Type %s is undefined.", name);
238227
exit(70);

test/features/type.lox

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace test.features;
2+
3+
Number sum(Number a, Int b) {
4+
return a + b;
5+
}
6+
7+
println(3.5 + 5);

0 commit comments

Comments
 (0)