Commit 1062ffb9 authored by Daniel Clifford's avatar Daniel Clifford Committed by Commit Bot

[torque]: Implement structs

Struct are bundles of value types. They are essentially just shorthand
for passing around a group of individually defined values.

Struct types are declared like this:

  struct A {
    x: Smi;
    y: int32;
  }

and can be constructed explicitly like this:

  A{0, 0}

Structs can be used wherever other types are used (e.g. variables,
parameters, return values) except for parameter/return types of
builtins and runtime functions.

Struct use field access notation to set/get their values like this:

  let a: A = A{0, 0};
  let b: Smi = a.x;
  a.y = 0;

Change-Id: I9fd36a6514c37882831256a49a50809c5db75b56
Reviewed-on: https://chromium-review.googlesource.com/1122133
Commit-Queue: Daniel Clifford <danno@chromium.org>
Reviewed-by: 's avatarTobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54501}
parent 16af1baa
......@@ -190,9 +190,11 @@ unaryExpression
| op=(PLUS | MINUS | BIT_NOT | NOT) unaryExpression;
locationExpression
: IDENTIFIER genericSpecializationTypeList?
: IDENTIFIER
| locationExpression '.' IDENTIFIER
| locationExpression '[' expression ']';
| primaryExpression '.' IDENTIFIER
| locationExpression '[' expression ']'
| primaryExpression '[' expression ']';
incrementDecrement
: INCREMENT locationExpression
......@@ -206,14 +208,24 @@ assignment
| locationExpression ((ASSIGNMENT | ASSIGNMENT_OPERATOR) expression)?;
assignmentExpression
: primaryExpression
: functionPointerExpression
| assignment;
structExpression
: IDENTIFIER '{' (expression (',' expression)*)? '}';
functionPointerExpression
: primaryExpression
| IDENTIFIER genericSpecializationTypeList?
;
primaryExpression
: helperCall
| structExpression
| DECIMAL_LITERAL
| STRING_LITERAL
| ('(' expression ')');
| ('(' expression ')')
;
forInitialization : variableDeclarationWithInitialization?;
forLoop: FOR '(' forInitialization ';' expression ';' assignment ')' statementBlock;
......@@ -266,6 +278,9 @@ statementBlock
helperBody : statementScope;
fieldDeclaration: IDENTIFIER ':' type ';';
fieldListDeclaration: fieldDeclaration*;
extendsDeclaration: 'extends' IDENTIFIER;
generatesDeclaration: 'generates' STRING_LITERAL;
constexprDeclaration: 'constexpr' STRING_LITERAL;
......@@ -280,9 +295,11 @@ genericSpecialization: IDENTIFIER genericSpecializationTypeList parameterList op
macroDeclaration : ('operator' STRING_LITERAL)? MACRO IDENTIFIER optionalGenericTypeList parameterList optionalType optionalLabelList (helperBody | ';');
externConstDeclaration : CONST IDENTIFIER ':' type generatesDeclaration ';';
constDeclaration: CONST IDENTIFIER ':' type ASSIGNMENT expression ';';
structDeclaration : 'struct' IDENTIFIER '{' fieldListDeclaration '}';
declaration
: typeDeclaration
: structDeclaration
| typeDeclaration
| typeAliasDeclaration
| builtinDeclaration
| genericSpecialization
......
This diff is collapsed.
T__0=1
T__1=2
T__2=3
T__3=4
T__4=5
T__5=6
T__6=7
T__7=8
T__8=9
T__9=10
T__10=11
T__11=12
T__12=13
T__13=14
T__14=15
T__15=16
T__16=17
T__17=18
T__18=19
T__19=20
T__20=21
MACRO=22
BUILTIN=23
RUNTIME=24
MODULE=25
JAVASCRIPT=26
DEFERRED=27
IF=28
FOR=29
WHILE=30
RETURN=31
CONSTEXPR=32
CONTINUE=33
BREAK=34
GOTO=35
OTHERWISE=36
TRY=37
LABEL=38
LABELS=39
TAIL=40
ISNT=41
IS=42
LET=43
CONST=44
EXTERN=45
ASSERT_TOKEN=46
CHECK_TOKEN=47
UNREACHABLE_TOKEN=48
DEBUG_TOKEN=49
ASSIGNMENT=50
ASSIGNMENT_OPERATOR=51
EQUAL=52
PLUS=53
MINUS=54
MULTIPLY=55
DIVIDE=56
MODULO=57
BIT_OR=58
BIT_AND=59
BIT_NOT=60
MAX=61
MIN=62
NOT_EQUAL=63
LESS_THAN=64
LESS_THAN_EQUAL=65
GREATER_THAN=66
GREATER_THAN_EQUAL=67
SHIFT_LEFT=68
SHIFT_RIGHT=69
SHIFT_RIGHT_ARITHMETIC=70
VARARGS=71
EQUALITY_OPERATOR=72
INCREMENT=73
DECREMENT=74
NOT=75
STRING_LITERAL=76
IDENTIFIER=77
WS=78
BLOCK_COMMENT=79
LINE_COMMENT=80
DECIMAL_LITERAL=81
'('=1
')'=2
'=>'=3
','=4
':'=5
'type'=6
'?'=7
'||'=8
'&&'=9
'.'=10
'['=11
']'=12
'{'=13
'}'=14
';'=15
'of'=16
'else'=17
'extends'=18
'generates'=19
'operator'=20
'struct'=21
'macro'=22
'builtin'=23
'runtime'=24
'module'=25
'javascript'=26
'deferred'=27
'if'=28
'for'=29
'while'=30
'return'=31
'constexpr'=32
'continue'=33
'break'=34
'goto'=35
'otherwise'=36
'try'=37
'label'=38
'labels'=39
'tail'=40
'isnt'=41
'is'=42
'let'=43
'const'=44
'extern'=45
'assert'=46
'check'=47
'unreachable'=48
'debug'=49
'='=50
'=='=52
'+'=53
'-'=54
'*'=55
'/'=56
'%'=57
'|'=58
'&'=59
'~'=60
'max'=61
'min'=62
'!='=63
'<'=64
'<='=65
'>'=66
'>='=67
'<<'=68
'>>'=69
'>>>'=70
'...'=71
'++'=73
'--'=74
'!'=75
......@@ -141,6 +141,16 @@ class TorqueBaseListener : public TorqueListener {
void exitAssignmentExpression(
TorqueParser::AssignmentExpressionContext* /*ctx*/) override {}
void enterStructExpression(
TorqueParser::StructExpressionContext* /*ctx*/) override {}
void exitStructExpression(
TorqueParser::StructExpressionContext* /*ctx*/) override {}
void enterFunctionPointerExpression(
TorqueParser::FunctionPointerExpressionContext* /*ctx*/) override {}
void exitFunctionPointerExpression(
TorqueParser::FunctionPointerExpressionContext* /*ctx*/) override {}
void enterPrimaryExpression(
TorqueParser::PrimaryExpressionContext* /*ctx*/) override {}
void exitPrimaryExpression(
......@@ -263,6 +273,16 @@ class TorqueBaseListener : public TorqueListener {
void enterHelperBody(TorqueParser::HelperBodyContext* /*ctx*/) override {}
void exitHelperBody(TorqueParser::HelperBodyContext* /*ctx*/) override {}
void enterFieldDeclaration(
TorqueParser::FieldDeclarationContext* /*ctx*/) override {}
void exitFieldDeclaration(
TorqueParser::FieldDeclarationContext* /*ctx*/) override {}
void enterFieldListDeclaration(
TorqueParser::FieldListDeclarationContext* /*ctx*/) override {}
void exitFieldListDeclaration(
TorqueParser::FieldListDeclarationContext* /*ctx*/) override {}
void enterExtendsDeclaration(
TorqueParser::ExtendsDeclarationContext* /*ctx*/) override {}
void exitExtendsDeclaration(
......@@ -328,6 +348,11 @@ class TorqueBaseListener : public TorqueListener {
void exitConstDeclaration(
TorqueParser::ConstDeclarationContext* /*ctx*/) override {}
void enterStructDeclaration(
TorqueParser::StructDeclarationContext* /*ctx*/) override {}
void exitStructDeclaration(
TorqueParser::StructDeclarationContext* /*ctx*/) override {}
void enterDeclaration(TorqueParser::DeclarationContext* /*ctx*/) override {}
void exitDeclaration(TorqueParser::DeclarationContext* /*ctx*/) override {}
......
......@@ -148,6 +148,16 @@ class TorqueBaseVisitor : public TorqueVisitor {
return visitChildren(ctx);
}
antlrcpp::Any visitStructExpression(
TorqueParser::StructExpressionContext* ctx) override {
return visitChildren(ctx);
}
antlrcpp::Any visitFunctionPointerExpression(
TorqueParser::FunctionPointerExpressionContext* ctx) override {
return visitChildren(ctx);
}
antlrcpp::Any visitPrimaryExpression(
TorqueParser::PrimaryExpressionContext* ctx) override {
return visitChildren(ctx);
......@@ -281,6 +291,16 @@ class TorqueBaseVisitor : public TorqueVisitor {
return visitChildren(ctx);
}
antlrcpp::Any visitFieldDeclaration(
TorqueParser::FieldDeclarationContext* ctx) override {
return visitChildren(ctx);
}
antlrcpp::Any visitFieldListDeclaration(
TorqueParser::FieldListDeclarationContext* ctx) override {
return visitChildren(ctx);
}
antlrcpp::Any visitExtendsDeclaration(
TorqueParser::ExtendsDeclarationContext* ctx) override {
return visitChildren(ctx);
......@@ -346,6 +366,11 @@ class TorqueBaseVisitor : public TorqueVisitor {
return visitChildren(ctx);
}
antlrcpp::Any visitStructDeclaration(
TorqueParser::StructDeclarationContext* ctx) override {
return visitChildren(ctx);
}
antlrcpp::Any visitDeclaration(
TorqueParser::DeclarationContext* ctx) override {
return visitChildren(ctx);
......
This diff is collapsed.
......@@ -33,66 +33,67 @@ class TorqueLexer : public antlr4::Lexer {
T__17 = 18,
T__18 = 19,
T__19 = 20,
MACRO = 21,
BUILTIN = 22,
RUNTIME = 23,
MODULE = 24,
JAVASCRIPT = 25,
DEFERRED = 26,
IF = 27,
FOR = 28,
WHILE = 29,
RETURN = 30,
CONSTEXPR = 31,
CONTINUE = 32,
BREAK = 33,
GOTO = 34,
OTHERWISE = 35,
TRY = 36,
LABEL = 37,
LABELS = 38,
TAIL = 39,
ISNT = 40,
IS = 41,
LET = 42,
CONST = 43,
EXTERN = 44,
ASSERT_TOKEN = 45,
CHECK_TOKEN = 46,
UNREACHABLE_TOKEN = 47,
DEBUG_TOKEN = 48,
ASSIGNMENT = 49,
ASSIGNMENT_OPERATOR = 50,
EQUAL = 51,
PLUS = 52,
MINUS = 53,
MULTIPLY = 54,
DIVIDE = 55,
MODULO = 56,
BIT_OR = 57,
BIT_AND = 58,
BIT_NOT = 59,
MAX = 60,
MIN = 61,
NOT_EQUAL = 62,
LESS_THAN = 63,
LESS_THAN_EQUAL = 64,
GREATER_THAN = 65,
GREATER_THAN_EQUAL = 66,
SHIFT_LEFT = 67,
SHIFT_RIGHT = 68,
SHIFT_RIGHT_ARITHMETIC = 69,
VARARGS = 70,
EQUALITY_OPERATOR = 71,
INCREMENT = 72,
DECREMENT = 73,
NOT = 74,
STRING_LITERAL = 75,
IDENTIFIER = 76,
WS = 77,
BLOCK_COMMENT = 78,
LINE_COMMENT = 79,
DECIMAL_LITERAL = 80
T__20 = 21,
MACRO = 22,
BUILTIN = 23,
RUNTIME = 24,
MODULE = 25,
JAVASCRIPT = 26,
DEFERRED = 27,
IF = 28,
FOR = 29,
WHILE = 30,
RETURN = 31,
CONSTEXPR = 32,
CONTINUE = 33,
BREAK = 34,
GOTO = 35,
OTHERWISE = 36,
TRY = 37,
LABEL = 38,
LABELS = 39,
TAIL = 40,
ISNT = 41,
IS = 42,
LET = 43,
CONST = 44,
EXTERN = 45,
ASSERT_TOKEN = 46,
CHECK_TOKEN = 47,
UNREACHABLE_TOKEN = 48,
DEBUG_TOKEN = 49,
ASSIGNMENT = 50,
ASSIGNMENT_OPERATOR = 51,
EQUAL = 52,
PLUS = 53,
MINUS = 54,
MULTIPLY = 55,
DIVIDE = 56,
MODULO = 57,
BIT_OR = 58,
BIT_AND = 59,
BIT_NOT = 60,
MAX = 61,
MIN = 62,
NOT_EQUAL = 63,
LESS_THAN = 64,
LESS_THAN_EQUAL = 65,
GREATER_THAN = 66,
GREATER_THAN_EQUAL = 67,
SHIFT_LEFT = 68,
SHIFT_RIGHT = 69,
SHIFT_RIGHT_ARITHMETIC = 70,
VARARGS = 71,
EQUALITY_OPERATOR = 72,
INCREMENT = 73,
DECREMENT = 74,
NOT = 75,
STRING_LITERAL = 76,
IDENTIFIER = 77,
WS = 78,
BLOCK_COMMENT = 79,
LINE_COMMENT = 80,
DECIMAL_LITERAL = 81
};
explicit TorqueLexer(antlr4::CharStream* input);
......
This diff is collapsed.
T__0=1
T__1=2
T__2=3
T__3=4
T__4=5
T__5=6
T__6=7
T__7=8
T__8=9
T__9=10
T__10=11
T__11=12
T__12=13
T__13=14
T__14=15
T__15=16
T__16=17
T__17=18
T__18=19
T__19=20
T__20=21
MACRO=22
BUILTIN=23
RUNTIME=24
MODULE=25
JAVASCRIPT=26
DEFERRED=27
IF=28
FOR=29
WHILE=30
RETURN=31
CONSTEXPR=32
CONTINUE=33
BREAK=34
GOTO=35
OTHERWISE=36
TRY=37
LABEL=38
LABELS=39
TAIL=40
ISNT=41
IS=42
LET=43
CONST=44
EXTERN=45
ASSERT_TOKEN=46
CHECK_TOKEN=47
UNREACHABLE_TOKEN=48
DEBUG_TOKEN=49
ASSIGNMENT=50
ASSIGNMENT_OPERATOR=51
EQUAL=52
PLUS=53
MINUS=54
MULTIPLY=55
DIVIDE=56
MODULO=57
BIT_OR=58
BIT_AND=59
BIT_NOT=60
MAX=61
MIN=62
NOT_EQUAL=63
LESS_THAN=64
LESS_THAN_EQUAL=65
GREATER_THAN=66
GREATER_THAN_EQUAL=67
SHIFT_LEFT=68
SHIFT_RIGHT=69
SHIFT_RIGHT_ARITHMETIC=70
VARARGS=71
EQUALITY_OPERATOR=72
INCREMENT=73
DECREMENT=74
NOT=75
STRING_LITERAL=76
IDENTIFIER=77
WS=78
BLOCK_COMMENT=79
LINE_COMMENT=80
DECIMAL_LITERAL=81
'('=1
')'=2
'=>'=3
','=4
':'=5
'type'=6
'?'=7
'||'=8
'&&'=9
'.'=10
'['=11
']'=12
'{'=13
'}'=14
';'=15
'of'=16
'else'=17
'extends'=18
'generates'=19
'operator'=20
'struct'=21
'macro'=22
'builtin'=23
'runtime'=24
'module'=25
'javascript'=26
'deferred'=27
'if'=28
'for'=29
'while'=30
'return'=31
'constexpr'=32
'continue'=33
'break'=34
'goto'=35
'otherwise'=36
'try'=37
'label'=38
'labels'=39
'tail'=40
'isnt'=41
'is'=42
'let'=43
'const'=44
'extern'=45
'assert'=46
'check'=47
'unreachable'=48
'debug'=49
'='=50
'=='=52
'+'=53
'-'=54
'*'=55
'/'=56
'%'=57
'|'=58
'&'=59
'~'=60
'max'=61
'min'=62
'!='=63
'<'=64
'<='=65
'>'=66
'>='=67
'<<'=68
'>>'=69
'>>>'=70
'...'=71
'++'=73
'--'=74
'!'=75
......@@ -137,6 +137,16 @@ class TorqueListener : public antlr4::tree::ParseTreeListener {
virtual void exitAssignmentExpression(
TorqueParser::AssignmentExpressionContext* ctx) = 0;
virtual void enterStructExpression(
TorqueParser::StructExpressionContext* ctx) = 0;
virtual void exitStructExpression(
TorqueParser::StructExpressionContext* ctx) = 0;
virtual void enterFunctionPointerExpression(
TorqueParser::FunctionPointerExpressionContext* ctx) = 0;
virtual void exitFunctionPointerExpression(
TorqueParser::FunctionPointerExpressionContext* ctx) = 0;
virtual void enterPrimaryExpression(
TorqueParser::PrimaryExpressionContext* ctx) = 0;
virtual void exitPrimaryExpression(
......@@ -248,6 +258,16 @@ class TorqueListener : public antlr4::tree::ParseTreeListener {
virtual void enterHelperBody(TorqueParser::HelperBodyContext* ctx) = 0;
virtual void exitHelperBody(TorqueParser::HelperBodyContext* ctx) = 0;
virtual void enterFieldDeclaration(
TorqueParser::FieldDeclarationContext* ctx) = 0;
virtual void exitFieldDeclaration(
TorqueParser::FieldDeclarationContext* ctx) = 0;
virtual void enterFieldListDeclaration(
TorqueParser::FieldListDeclarationContext* ctx) = 0;
virtual void exitFieldListDeclaration(
TorqueParser::FieldListDeclarationContext* ctx) = 0;
virtual void enterExtendsDeclaration(
TorqueParser::ExtendsDeclarationContext* ctx) = 0;
virtual void exitExtendsDeclaration(
......@@ -311,6 +331,11 @@ class TorqueListener : public antlr4::tree::ParseTreeListener {
virtual void exitConstDeclaration(
TorqueParser::ConstDeclarationContext* ctx) = 0;
virtual void enterStructDeclaration(
TorqueParser::StructDeclarationContext* ctx) = 0;
virtual void exitStructDeclaration(
TorqueParser::StructDeclarationContext* ctx) = 0;
virtual void enterDeclaration(TorqueParser::DeclarationContext* ctx) = 0;
virtual void exitDeclaration(TorqueParser::DeclarationContext* ctx) = 0;
......
This diff is collapsed.
This diff is collapsed.
......@@ -100,6 +100,12 @@ class TorqueVisitor : public antlr4::tree::AbstractParseTreeVisitor {
virtual antlrcpp::Any visitAssignmentExpression(
TorqueParser::AssignmentExpressionContext* context) = 0;
virtual antlrcpp::Any visitStructExpression(
TorqueParser::StructExpressionContext* context) = 0;
virtual antlrcpp::Any visitFunctionPointerExpression(
TorqueParser::FunctionPointerExpressionContext* context) = 0;
virtual antlrcpp::Any visitPrimaryExpression(
TorqueParser::PrimaryExpressionContext* context) = 0;
......@@ -183,6 +189,12 @@ class TorqueVisitor : public antlr4::tree::AbstractParseTreeVisitor {
virtual antlrcpp::Any visitHelperBody(
TorqueParser::HelperBodyContext* context) = 0;
virtual antlrcpp::Any visitFieldDeclaration(
TorqueParser::FieldDeclarationContext* context) = 0;
virtual antlrcpp::Any visitFieldListDeclaration(
TorqueParser::FieldListDeclarationContext* context) = 0;
virtual antlrcpp::Any visitExtendsDeclaration(
TorqueParser::ExtendsDeclarationContext* context) = 0;
......@@ -222,6 +234,9 @@ class TorqueVisitor : public antlr4::tree::AbstractParseTreeVisitor {
virtual antlrcpp::Any visitConstDeclaration(
TorqueParser::ConstDeclarationContext* context) = 0;
virtual antlrcpp::Any visitStructDeclaration(
TorqueParser::StructDeclarationContext* context) = 0;
virtual antlrcpp::Any visitDeclaration(
TorqueParser::DeclarationContext* context) = 0;
......
......@@ -545,6 +545,21 @@ antlrcpp::Any AstGenerator::visitTryLabelStatement(
return implicit_cast<Statement*>(result);
}
antlrcpp::Any AstGenerator::visitFunctionPointerExpression(
TorqueParser::FunctionPointerExpressionContext* context) {
if (context->IDENTIFIER()) {
std::vector<TypeExpression*> templateArguments;
if (context->genericSpecializationTypeList()) {
templateArguments =
GetTypeVector(context->genericSpecializationTypeList()->typeList());
}
return implicit_cast<Expression*>(RegisterNode(new IdentifierExpression{
Pos(context), context->IDENTIFIER()->getSymbol()->getText(),
std::move(templateArguments)}));
}
return context->primaryExpression()->accept(this);
}
antlrcpp::Any AstGenerator::visitPrimaryExpression(
TorqueParser::PrimaryExpressionContext* context) {
if (auto* e = context->helperCall()) return e->accept(this);
......@@ -554,9 +569,23 @@ antlrcpp::Any AstGenerator::visitPrimaryExpression(
if (auto* e = context->STRING_LITERAL())
return implicit_cast<Expression*>(RegisterNode(
new StringLiteralExpression{Pos(context), e->getSymbol()->getText()}));
if (context->structExpression()) {
return context->structExpression()->accept(this);
}
return context->expression()->accept(this);
}
antlrcpp::Any AstGenerator::visitStructExpression(
TorqueParser::StructExpressionContext* context) {
std::vector<Expression*> expressions;
for (auto& e : context->expression()) {
expressions.push_back(e->accept(this).as<Expression*>());
}
return implicit_cast<Expression*>(RegisterNode(new StructExpression{
Pos(context), context->IDENTIFIER()->getSymbol()->getText(),
expressions}));
}
antlrcpp::Any AstGenerator::visitAssignment(
TorqueParser::AssignmentContext* context) {
if (auto* e = context->incrementDecrement()) return e->accept(this);
......@@ -589,25 +618,23 @@ antlrcpp::Any AstGenerator::visitIncrementDecrement(
antlrcpp::Any AstGenerator::visitLocationExpression(
TorqueParser::LocationExpressionContext* context) {
if (auto* l = context->locationExpression()) {
Expression* location = l->accept(this).as<Expression*>();
if (auto* e = context->expression()) {
return implicit_cast<Expression*>(
RegisterNode(new ElementAccessExpression{
Pos(context), location, e->accept(this).as<Expression*>()}));
}
return implicit_cast<Expression*>(RegisterNode(new FieldAccessExpression{
Pos(context), location,
context->IDENTIFIER()->getSymbol()->getText()}));
Expression* location = nullptr;
if (auto* p = context->primaryExpression()) {
location = p->accept(this).as<Expression*>();
} else if (auto* l = context->locationExpression()) {
location = l->accept(this).as<Expression*>();
} else {
return implicit_cast<Expression*>(RegisterNode(new IdentifierExpression{
Pos(context), context->IDENTIFIER()->getSymbol()->getText(), {}}));
}
std::vector<TypeExpression*> templateArguments;
if (context->genericSpecializationTypeList()) {
templateArguments =
GetTypeVector(context->genericSpecializationTypeList()->typeList());
if (auto* e = context->expression()) {
return implicit_cast<Expression*>(RegisterNode(new ElementAccessExpression{
Pos(context), location, e->accept(this).as<Expression*>()}));
}
return implicit_cast<Expression*>(RegisterNode(new IdentifierExpression{
Pos(context), context->IDENTIFIER()->getSymbol()->getText(),
std::move(templateArguments)}));
return implicit_cast<Expression*>(RegisterNode(new FieldAccessExpression{
Pos(context), location, context->IDENTIFIER()->getSymbol()->getText()}));
}
antlrcpp::Any AstGenerator::visitUnaryExpression(
......@@ -768,6 +795,22 @@ antlrcpp::Any AstGenerator::visitDiagnosticStatement(
}
}
antlrcpp::Any AstGenerator::visitStructDeclaration(
TorqueParser::StructDeclarationContext* context) {
StructDeclaration* struct_declaration = RegisterNode(new StructDeclaration{
Pos(context), context->IDENTIFIER()->getSymbol()->getText()});
for (auto* fieldDeclaration :
context->fieldListDeclaration()->fieldDeclaration()) {
FieldNameAndType field = {
fieldDeclaration->IDENTIFIER()->getSymbol()->getText(),
GetType(fieldDeclaration->type())};
struct_declaration->fields.push_back(field);
}
return implicit_cast<Declaration*>(struct_declaration);
}
void AstGenerator::visitSourceFile(SourceFileContext* context) {
source_file_context_ = context;
current_source_file_ = SourceFileMap::Get().AddSource(context->name);
......
......@@ -69,6 +69,9 @@ class AstGenerator : public TorqueBaseVisitor {
antlrcpp::Any visitHelperCallStatement(
TorqueParser::HelperCallStatementContext* context) override;
antlrcpp::Any visitStructExpression(
TorqueParser::StructExpressionContext* context) override;
antlrcpp::Any visitConditionalExpression(
TorqueParser::ConditionalExpressionContext* context) override;
......@@ -108,6 +111,9 @@ class AstGenerator : public TorqueBaseVisitor {
antlrcpp::Any visitAssignment(
TorqueParser::AssignmentContext* context) override;
antlrcpp::Any visitFunctionPointerExpression(
TorqueParser::FunctionPointerExpressionContext* context) override;
antlrcpp::Any visitPrimaryExpression(
TorqueParser::PrimaryExpressionContext* context) override;
......@@ -146,6 +152,9 @@ class AstGenerator : public TorqueBaseVisitor {
antlrcpp::Any visitDiagnosticStatement(
TorqueParser::DiagnosticStatementContext* context) override;
antlrcpp::Any visitStructDeclaration(
TorqueParser::StructDeclarationContext* context) override;
antlrcpp::Any aggregateResult(antlrcpp::Any aggregate,
const antlrcpp::Any& nextResult) override {
if (aggregate.isNull())
......
......@@ -29,6 +29,7 @@ DECLARE_CONTEXTUAL_VARIABLE(CurrentSourcePosition, SourcePosition)
#define AST_EXPRESSION_NODE_KIND_LIST(V) \
V(CallExpression) \
V(StructExpression) \
V(LogicalOrExpression) \
V(LogicalAndExpression) \
V(ConditionalExpression) \
......@@ -69,6 +70,7 @@ DECLARE_CONTEXTUAL_VARIABLE(CurrentSourcePosition, SourcePosition)
V(GenericDeclaration) \
V(SpecializationDeclaration) \
V(ExternConstDeclaration) \
V(StructDeclaration) \
V(DefaultModuleDeclaration) \
V(ExplicitModuleDeclaration) \
V(ConstDeclaration)
......@@ -260,6 +262,14 @@ struct CallExpression : Expression {
std::vector<std::string> labels;
};
struct StructExpression : Expression {
DEFINE_AST_NODE_LEAF_BOILERPLATE(StructExpression)
StructExpression(SourcePosition p, std::string n, std::vector<Expression*> e)
: Expression(kKind, p), name(n), expressions(std::move(e)) {}
std::string name;
std::vector<Expression*> expressions;
};
struct LogicalOrExpression : Expression {
DEFINE_AST_NODE_LEAF_BOILERPLATE(LogicalOrExpression)
LogicalOrExpression(SourcePosition p, Expression* l, Expression* r)
......@@ -552,6 +562,11 @@ struct TypeAliasDeclaration : Declaration {
TypeExpression* type;
};
struct FieldNameAndType {
std::string name;
TypeExpression* type;
};
struct LabelAndTypes {
std::string name;
std::vector<TypeExpression*> types;
......@@ -693,6 +708,14 @@ struct ExternConstDeclaration : Declaration {
std::string literal;
};
struct StructDeclaration : Declaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(StructDeclaration)
StructDeclaration(SourcePosition p, std::string n)
: Declaration(kKind, p), name(std::move(n)) {}
std::string name;
std::vector<FieldNameAndType> fields;
};
#define ENUM_ITEM(name) \
case AstNode::Kind::k##name: \
return std::is_base_of<T, name>::value; \
......
......@@ -34,6 +34,18 @@ std::ostream& operator<<(std::ostream& os, const RuntimeFunction& b) {
return os;
}
std::string Variable::RValue() const {
if (!IsDefined()) {
ReportError("Reading uninitialized variable.");
}
if (type()->IsStructType()) {
return value();
}
std::string result = "(*" + value() + ")";
if (!IsConst()) result += ".value()";
return result;
}
void PrintLabel(std::ostream& os, const Label& l, bool with_names) {
os << l.name();
if (l.GetParameterCount() != 0) {
......
......@@ -134,14 +134,7 @@ class Variable : public Value {
DECLARE_DECLARABLE_BOILERPLATE(Variable, variable);
bool IsConst() const override { return const_; }
std::string value() const override { return value_; }
std::string RValue() const override {
if (!IsDefined()) {
ReportError("Reading uninitialized variable.");
}
std::string result = "(*" + value() + ")";
if (!IsConst()) result += ".value()";
return result;
}
std::string RValue() const override;
void Define() {
if (defined_ && IsConst()) {
ReportError("Cannot re-define a const-bound variable.");
......
......@@ -95,6 +95,15 @@ Builtin* DeclarationVisitor::BuiltinDeclarationCommon(
}
}
if (const StructType* struct_type =
StructType::DynamicCast(signature.return_type)) {
std::stringstream stream;
stream << "builtins (in this case" << decl->name
<< ") cannot return structs (in this case " << struct_type->name()
<< ")";
ReportError(stream.str());
}
std::string generated_name = GetGeneratedCallableName(
decl->name, declarations()->GetCurrentSpecializationTypeNamesVector());
return declarations()->DeclareBuiltin(generated_name, kind, external,
......@@ -117,6 +126,15 @@ void DeclarationVisitor::Visit(ExternalRuntimeDeclaration* decl,
ReportError(stream.str());
}
if (signature.return_type->IsStructType()) {
std::stringstream stream;
stream << "runtime functions (in this case" << decl->name
<< ") cannot return structs (in this case "
<< static_cast<const StructType*>(signature.return_type)->name()
<< ")";
ReportError(stream.str());
}
declarations()->DeclareRuntimeFunction(decl->name, signature);
}
......@@ -158,9 +176,9 @@ void DeclarationVisitor::Visit(TorqueMacroDeclaration* decl,
DeclareSignature(signature);
Variable* return_variable = nullptr;
if (!signature.return_type->IsVoidOrNever()) {
return_variable = declarations()->DeclareVariable(
kReturnValueVariable, signature.return_type,
signature.return_type->IsConstexpr());
return_variable =
DeclareVariable(kReturnValueVariable, signature.return_type,
signature.return_type->IsConstexpr());
}
PushControlSplit();
......@@ -252,6 +270,33 @@ void DeclarationVisitor::Visit(ReturnStatement* stmt) {
}
}
Variable* DeclarationVisitor::DeclareVariable(const std::string& name,
const Type* type, bool is_const) {
Variable* result = declarations()->DeclareVariable(name, type, is_const);
if (type->IsStructType()) {
const StructType* struct_type = StructType::cast(type);
for (auto& field : struct_type->fields()) {
std::string field_var_name = name + "." + field.name;
DeclareVariable(field_var_name, field.type, is_const);
}
}
return result;
}
Parameter* DeclarationVisitor::DeclareParameter(const std::string& name,
const Type* type) {
Parameter* result = declarations()->DeclareParameter(
name, GetParameterVariableFromName(name), type);
if (type->IsStructType()) {
const StructType* struct_type = StructType::cast(type);
for (auto& field : struct_type->fields()) {
std::string field_var_name = name + "." + field.name;
DeclareParameter(field_var_name, field.type);
}
}
return result;
}
void DeclarationVisitor::Visit(VarDeclarationStatement* stmt) {
std::string variable_name = stmt->name;
const Type* type = declarations()->GetType(stmt->type);
......@@ -259,7 +304,7 @@ void DeclarationVisitor::Visit(VarDeclarationStatement* stmt) {
ReportError(
"cannot declare variable with constexpr type. Use 'const' instead.");
}
declarations()->DeclareVariable(variable_name, type, stmt->const_qualified);
DeclareVariable(variable_name, type, stmt->const_qualified);
if (global_context_.verbose()) {
std::cout << "declared variable " << variable_name << " with type " << *type
<< "\n";
......@@ -293,6 +338,15 @@ void DeclarationVisitor::Visit(ExternConstDeclaration* decl) {
declarations()->DeclareExternConstant(decl->name, type, decl->literal);
}
void DeclarationVisitor::Visit(StructDeclaration* decl) {
std::vector<NameAndType> fields;
for (auto& field : decl->fields) {
const Type* field_type = declarations()->GetType(field.type);
fields.push_back({field.name, field_type});
}
declarations()->DeclareStruct(CurrentModule(), decl->name, fields);
}
void DeclarationVisitor::Visit(LogicalOrExpression* expr) {
{
Declarations::NodeScopeActivator scope(declarations(), expr->left);
......@@ -415,8 +469,7 @@ void DeclarationVisitor::Visit(TryLabelStatement* stmt) {
ReportError("no constexpr type allowed for label arguments");
}
shared_label->AddVariable(
declarations()->DeclareVariable(p, type, false));
shared_label->AddVariable(DeclareVariable(p, type, false));
++i;
}
}
......@@ -556,8 +609,7 @@ void DeclarationVisitor::DeclareSignature(const Signature& signature) {
for (auto name : signature.parameter_names) {
const Type* t(*type_iterator++);
if (name.size() != 0) {
declarations()->DeclareParameter(name, GetParameterVariableFromName(name),
t);
DeclareParameter(name, t);
}
}
for (auto& label : signature.labels) {
......@@ -570,8 +622,7 @@ void DeclarationVisitor::DeclareSignature(const Signature& signature) {
}
std::string var_name = label.name + std::to_string(i++);
new_label->AddVariable(
declarations()->DeclareVariable(var_name, var_type, false));
new_label->AddVariable(DeclareVariable(var_name, var_type, false));
}
}
}
......
......@@ -108,6 +108,10 @@ class DeclarationVisitor : public FileVisitor {
void Visit(VarDeclarationStatement* stmt);
void Visit(ExternConstDeclaration* decl);
void Visit(StructDeclaration* decl);
void Visit(StructExpression* decl) {}
void Visit(LogicalOrExpression* expr);
void Visit(LogicalAndExpression* expr);
void DeclareExpressionForBranch(Expression* node);
......@@ -148,6 +152,10 @@ class DeclarationVisitor : public FileVisitor {
live_and_changed_variables_.push_back(live_and_changed);
}
Variable* DeclareVariable(const std::string& name, const Type* type,
bool is_const);
Parameter* DeclareParameter(const std::string& name, const Type* type);
std::set<const Variable*> PopControlSplit() {
auto result = live_and_changed_variables_.back().changed;
live_and_changed_variables_.pop_back();
......
......@@ -224,6 +224,12 @@ void Declarations::DeclareType(const std::string& name, const Type* type) {
Declare(name, std::unique_ptr<TypeAlias>(result));
}
void Declarations::DeclareStruct(Module* module, const std::string& name,
const std::vector<NameAndType>& fields) {
const StructType* new_type = TypeOracle::GetStructType(module, name, fields);
DeclareType(name, new_type);
}
Label* Declarations::DeclareLabel(const std::string& name) {
CheckAlreadyDeclared(name, "label");
Label* result = new Label(name);
......@@ -289,7 +295,9 @@ RuntimeFunction* Declarations::DeclareRuntimeFunction(
Variable* Declarations::DeclareVariable(const std::string& var,
const Type* type, bool is_const) {
std::string name(var + std::to_string(GetNextUniqueDeclarationNumber()));
std::string name(var + "_" +
std::to_string(GetNextUniqueDeclarationNumber()));
std::replace(name.begin(), name.end(), '.', '_');
CheckAlreadyDeclared(var, "variable");
Variable* result = new Variable(var, name, type, is_const);
Declare(var, std::unique_ptr<Declarable>(result));
......
......@@ -76,6 +76,9 @@ class Declarations {
void DeclareType(const std::string& name, const Type* type);
void DeclareStruct(Module* module, const std::string& name,
const std::vector<NameAndType>& fields);
Label* DeclareLabel(const std::string& name);
Macro* DeclareMacro(const std::string& name, const Signature& signature,
......
This diff is collapsed.
......@@ -37,35 +37,31 @@ class ImplementationVisitor : public FileVisitor {
const Type* Visit(Statement* stmt);
void Visit(Declaration* decl);
VisitResult Visit(StructExpression* decl);
LocationReference GetLocationReference(LocationExpression* location);
LocationReference GetLocationReference(IdentifierExpression* expr) {
return LocationReference(declarations()->LookupValue(expr->name), {}, {});
}
LocationReference GetLocationReference(FieldAccessExpression* expr) {
return LocationReference({}, Visit(expr->object), {});
}
LocationReference GetLocationReference(FieldAccessExpression* expr);
LocationReference GetLocationReference(ElementAccessExpression* expr) {
return LocationReference({}, Visit(expr->array), Visit(expr->index));
}
std::string RValueFlattenStructs(VisitResult result);
VisitResult GenerateFetchFromLocation(LocationReference reference) {
const Value* value = reference.value;
return VisitResult(value->type(), value);
}
VisitResult GenerateFetchFromLocation(LocationExpression* location,
LocationReference reference);
VisitResult GenerateFetchFromLocation(IdentifierExpression* expr,
LocationReference reference) {
Value* value = reference.value;
if (value->IsVariable() && !Variable::cast(value)->IsDefined()) {
std::stringstream s;
s << "\"" << value->name() << "\" is used before it is defined";
ReportError(s.str());
}
return VisitResult(value->type(), value);
return GenerateFetchFromLocation(reference);
}
VisitResult GenerateFetchFromLocation(FieldAccessExpression* expr,
LocationReference reference) {
Arguments arguments;
arguments.parameters = {reference.base};
return GenerateCall(std::string(".") + expr->field, arguments);
}
LocationReference reference);
VisitResult GenerateFetchFromLocation(ElementAccessExpression* expr,
LocationReference reference) {
Arguments arguments;
......@@ -93,6 +89,7 @@ class ImplementationVisitor : public FileVisitor {
void Visit(TypeDeclaration* decl) {}
void Visit(TypeAliasDeclaration* decl) {}
void Visit(ExternConstDeclaration* decl) {}
void Visit(StructDeclaration* decl);
void Visit(StandardDeclaration* decl);
void Visit(GenericDeclaration* decl) {}
void Visit(SpecializationDeclaration* decl);
......@@ -176,6 +173,11 @@ class ImplementationVisitor : public FileVisitor {
Callable* LookupCall(const std::string& name, const Arguments& arguments);
bool GenerateChangedVarFromControlSplit(const Variable* v, bool first = true);
void GetFlattenedStructsVars(const Variable* base,
std::set<const Variable*>& vars);
void GenerateChangedVarsFromControlSplit(AstNode* node);
const Type* GetCommonType(const Type* left, const Type* right);
......@@ -188,6 +190,8 @@ class ImplementationVisitor : public FileVisitor {
const LocationReference& reference,
VisitResult assignment_value);
void GenerateVariableDeclaration(const Variable* var);
Variable* GenerateVariableDeclaration(
AstNode* node, const std::string& name,
const base::Optional<const Type*>& type,
......
......@@ -29,6 +29,14 @@ class TypeOracle : public ContextualClass<TypeOracle> {
return result;
}
static const StructType* GetStructType(
Module* module, const std::string& name,
const std::vector<NameAndType>& fields) {
StructType* result = new StructType(module, name, fields);
Get().struct_types_.push_back(std::unique_ptr<StructType>(result));
return result;
}
static const FunctionPointerType* GetFunctionPointerType(
TypeVector argument_types, const Type* return_type) {
const Type* code_type = Get().GetBuiltinType(CODE_TYPE_STRING);
......@@ -101,6 +109,7 @@ class TypeOracle : public ContextualClass<TypeOracle> {
Deduplicator<FunctionPointerType> function_pointer_types_;
Deduplicator<UnionType> union_types_;
std::vector<std::unique_ptr<Type>> nominal_types_;
std::vector<std::unique_ptr<Type>> struct_types_;
};
} // namespace torque
......
......@@ -154,6 +154,14 @@ const Type* UnionType::NonConstexprVersion() const {
return this;
}
std::string StructType::ToExplicitString() const {
std::stringstream result;
result << "{";
PrintCommaSeparatedList(result, fields_);
result << "}";
return result.str();
}
void PrintSignature(std::ostream& os, const Signature& sig, bool with_names) {
os << "(";
for (size_t i = 0; i < sig.parameter_types.types.size(); ++i) {
......@@ -181,6 +189,13 @@ void PrintSignature(std::ostream& os, const Signature& sig, bool with_names) {
}
}
std::ostream& operator<<(std::ostream& os, const NameAndType& name_and_type) {
os << name_and_type.name;
os << ": ";
os << *name_and_type.type;
return os;
}
std::ostream& operator<<(std::ostream& os, const Signature& sig) {
PrintSignature(os, sig, true);
return os;
......@@ -256,7 +271,17 @@ std::string VisitResult::LValue() const {
}
std::string VisitResult::RValue() const {
return declarable_ ? (*declarable_)->RValue() : value_;
if (declarable()) {
auto value = *declarable();
if (value->IsVariable() && !Variable::cast(value)->IsDefined()) {
std::stringstream s;
s << "\"" << value->name() << "\" is used before it is defined";
ReportError(s.str());
}
return value->RValue();
} else {
return value_;
}
}
} // namespace torque
......
......@@ -37,13 +37,19 @@ class Value;
class TypeBase {
public:
enum class Kind { kAbstractType, kFunctionPointerType, kUnionType };
enum class Kind {
kAbstractType,
kFunctionPointerType,
kUnionType,
kStructType
};
virtual ~TypeBase() {}
bool IsAbstractType() const { return kind() == Kind::kAbstractType; }
bool IsFunctionPointerType() const {
return kind() == Kind::kFunctionPointerType;
}
bool IsUnionType() const { return kind() == Kind::kUnionType; }
bool IsStructType() const { return kind() == Kind::kStructType; }
protected:
explicit TypeBase(Kind kind) : kind_(kind) {}
......@@ -111,6 +117,13 @@ class Type : public TypeBase {
using TypeVector = std::vector<const Type*>;
struct NameAndType {
std::string name;
const Type* type;
};
std::ostream& operator<<(std::ostream& os, const NameAndType& name_and_type);
class AbstractType final : public Type {
public:
DECLARE_TYPE_BOILERPLATE(AbstractType);
......@@ -285,6 +298,37 @@ class UnionType final : public Type {
std::set<const Type*, TypeLess> types_;
};
class StructType final : public Type {
public:
DECLARE_TYPE_BOILERPLATE(StructType);
std::string ToExplicitString() const override;
std::string MangledName() const override { return name_; }
std::string GetGeneratedTypeName() const override { return GetStructName(); }
std::string GetGeneratedTNodeTypeName() const override { UNREACHABLE(); }
const Type* NonConstexprVersion() const override { return this; }
bool IsConstexpr() const override { return false; }
const std::vector<NameAndType>& fields() const { return fields_; }
const std::string& name() const { return name_; }
Module* module() const { return module_; }
private:
friend class TypeOracle;
StructType(Module* module, const std::string& name,
const std::vector<NameAndType>& fields)
: Type(Kind::kStructType, nullptr),
module_(module),
name_(name),
fields_(fields) {}
const std::string& GetStructName() const { return name_; }
Module* module_;
std::string name_;
std::vector<NameAndType> fields_;
};
inline std::ostream& operator<<(std::ostream& os, const Type& t) {
os << t.ToString();
return os;
......@@ -325,11 +369,6 @@ class VisitResultVector : public std::vector<VisitResult> {
std::ostream& operator<<(std::ostream& os, const TypeVector& types);
struct NameAndType {
std::string name;
const Type* type;
};
typedef std::vector<NameAndType> NameAndTypeVector;
struct LabelDefinition {
......
......@@ -4,9 +4,9 @@
module test {
macro ElementsKindTestHelper1(kind: constexpr ElementsKind): bool {
if constexpr ((kind == UINT8_ELEMENTS) || (kind == UINT16_ELEMENTS)) {
return true;
}
if constexpr((kind == UINT8_ELEMENTS) || (kind == UINT16_ELEMENTS)) {
return true;
}
else {
return false;
}
......@@ -82,7 +82,7 @@ module test {
}
}
builtin GenericBuiltinTest<T: type>(c: Context, param: T): Object {
builtin GenericBuiltinTest<T : type>(c: Context, param: T): Object {
return Null;
}
......@@ -98,7 +98,8 @@ module test {
}
macro LabelTestHelper4(flag: constexpr bool): never labels Label4, Label5 {
if constexpr (flag) goto Label4;
if
constexpr(flag) goto Label4;
else
goto Label5;
}
......@@ -125,7 +126,7 @@ module test {
return False;
}
macro GenericMacroTest<T: type>(param: T): Object {
macro GenericMacroTest<T : type>(param: T): Object {
return Undefined;
}
......@@ -133,7 +134,7 @@ module test {
return param2;
}
macro GenericMacroTestWithLabels<T: type>(param: T): Object labels X {
macro GenericMacroTestWithLabels<T : type>(param: T): Object labels X {
return Undefined;
}
......@@ -158,29 +159,29 @@ module test {
}
}
builtin TestHelperPlus1(context : Context, x : Smi) : Smi {
builtin TestHelperPlus1(context: Context, x: Smi): Smi {
return x + 1;
}
builtin TestHelperPlus2(context : Context, x : Smi) : Smi {
builtin TestHelperPlus2(context: Context, x: Smi): Smi {
return x + 2;
}
macro TestFunctionPointers(context : Context) : Boolean {
let fptr : builtin(Context, Smi) => Smi = TestHelperPlus1;
macro TestFunctionPointers(context: Context): Boolean {
let fptr: builtin(Context, Smi) => Smi = TestHelperPlus1;
check(fptr(context, 42) == 43);
fptr = TestHelperPlus2;
check(fptr(context, 42) == 44);
return True;
}
macro TestVariableRedeclaration(context : Context) : Boolean {
let var1 : int31 = from_constexpr<bool>(42 == 0) ? 0 : 1;
let var2 : int31 = from_constexpr<bool>(42 == 0) ? 1 : 0;
macro TestVariableRedeclaration(context: Context): Boolean {
let var1: int31 = from_constexpr<bool>(42 == 0) ? 0 : 1;
let var2: int31 = from_constexpr<bool>(42 == 0) ? 1 : 0;
return True;
}
macro TestTernaryOperator(x : Smi) : Smi {
let b : bool = x < 0 ? true : false;
macro TestTernaryOperator(x: Smi): Smi {
let b: bool = x < 0 ? true : false;
return b ? x - 10 : x + 100;
}
......@@ -195,7 +196,7 @@ module test {
}
type SmiToSmi = builtin(Smi) => Smi;
macro TestTypeAlias(x : SmiToSmi) : Code {
macro TestTypeAlias(x: SmiToSmi): Code {
return x;
}
......@@ -221,8 +222,9 @@ module test {
macro TestMultilineAssert() {
let someVeryLongVariableNameThatWillCauseLineBreaks: Smi = 5;
check(someVeryLongVariableNameThatWillCauseLineBreaks > 0
&& someVeryLongVariableNameThatWillCauseLineBreaks < 10);
check(
someVeryLongVariableNameThatWillCauseLineBreaks > 0 &&
someVeryLongVariableNameThatWillCauseLineBreaks < 10);
}
macro TestNewlineInString() {
......@@ -243,4 +245,48 @@ module test {
const kSmi: Smi = 3;
check(kSmi == 3);
}
struct TestStructA {
indexes: FixedArray;
i: Smi;
k: Number;
}
struct TestStructB {
x: TestStructA;
y: Smi;
}
macro TestStruct1(i: TestStructA): Smi {
return i.i;
}
macro TestStruct2(): TestStructA {
return TestStructA{unsafe_cast<FixedArray>(kEmptyFixedArray), 27, 31};
}
macro TestStruct3(): TestStructA {
let a: TestStructA =
TestStructA{unsafe_cast<FixedArray>(kEmptyFixedArray), 13, 5};
let b: TestStructA = a;
let c: TestStructA = TestStruct2();
a.i = TestStruct1(c);
a.k = a.i;
let d: TestStructB;
d.x = a;
d = TestStructB{a, 7};
let e: TestStructA = d.x;
let f: Smi = TestStructA{unsafe_cast<FixedArray>(kEmptyFixedArray), 27, 31}.i;
f = TestStruct2().i;
return a;
}
struct TestStructC {
x : TestStructA;
y : TestStructA;
}
macro TestStruct4(): TestStructC {
return TestStructC{TestStruct2(), TestStruct2()};
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment