[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: Tobias Tebbi <tebbi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#54501}
This commit is contained in:
Daniel Clifford 2018-07-17 18:20:53 +02:00 committed by Commit Bot
parent 16af1baac4
commit 1062ffb958
28 changed files with 4294 additions and 2245 deletions

View File

@ -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

249
src/torque/Torque.interp Normal file

File diff suppressed because one or more lines are too long

154
src/torque/Torque.tokens Normal file
View File

@ -0,0 +1,154 @@
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

View File

@ -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 {}

View File

@ -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);

File diff suppressed because it is too large Load Diff

View File

@ -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);

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,154 @@
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

View File

@ -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;

File diff suppressed because it is too large Load Diff

View File

@ -33,66 +33,67 @@ class TorqueParser : public antlr4::Parser {
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
};
enum {
@ -123,50 +124,55 @@ class TorqueParser : public antlr4::Parser {
RuleIncrementDecrement = 24,
RuleAssignment = 25,
RuleAssignmentExpression = 26,
RulePrimaryExpression = 27,
RuleForInitialization = 28,
RuleForLoop = 29,
RuleRangeSpecifier = 30,
RuleForOfRange = 31,
RuleForOfLoop = 32,
RuleArgument = 33,
RuleArgumentList = 34,
RuleHelperCall = 35,
RuleLabelReference = 36,
RuleVariableDeclaration = 37,
RuleVariableDeclarationWithInitialization = 38,
RuleHelperCallStatement = 39,
RuleExpressionStatement = 40,
RuleIfStatement = 41,
RuleWhileLoop = 42,
RuleReturnStatement = 43,
RuleBreakStatement = 44,
RuleContinueStatement = 45,
RuleGotoStatement = 46,
RuleHandlerWithStatement = 47,
RuleTryLabelStatement = 48,
RuleDiagnosticStatement = 49,
RuleStatement = 50,
RuleStatementList = 51,
RuleStatementScope = 52,
RuleStatementBlock = 53,
RuleHelperBody = 54,
RuleExtendsDeclaration = 55,
RuleGeneratesDeclaration = 56,
RuleConstexprDeclaration = 57,
RuleTypeDeclaration = 58,
RuleTypeAliasDeclaration = 59,
RuleExternalBuiltin = 60,
RuleExternalMacro = 61,
RuleExternalRuntime = 62,
RuleBuiltinDeclaration = 63,
RuleGenericSpecialization = 64,
RuleMacroDeclaration = 65,
RuleExternConstDeclaration = 66,
RuleConstDeclaration = 67,
RuleDeclaration = 68,
RuleModuleDeclaration = 69,
RuleFile = 70
RuleStructExpression = 27,
RuleFunctionPointerExpression = 28,
RulePrimaryExpression = 29,
RuleForInitialization = 30,
RuleForLoop = 31,
RuleRangeSpecifier = 32,
RuleForOfRange = 33,
RuleForOfLoop = 34,
RuleArgument = 35,
RuleArgumentList = 36,
RuleHelperCall = 37,
RuleLabelReference = 38,
RuleVariableDeclaration = 39,
RuleVariableDeclarationWithInitialization = 40,
RuleHelperCallStatement = 41,
RuleExpressionStatement = 42,
RuleIfStatement = 43,
RuleWhileLoop = 44,
RuleReturnStatement = 45,
RuleBreakStatement = 46,
RuleContinueStatement = 47,
RuleGotoStatement = 48,
RuleHandlerWithStatement = 49,
RuleTryLabelStatement = 50,
RuleDiagnosticStatement = 51,
RuleStatement = 52,
RuleStatementList = 53,
RuleStatementScope = 54,
RuleStatementBlock = 55,
RuleHelperBody = 56,
RuleFieldDeclaration = 57,
RuleFieldListDeclaration = 58,
RuleExtendsDeclaration = 59,
RuleGeneratesDeclaration = 60,
RuleConstexprDeclaration = 61,
RuleTypeDeclaration = 62,
RuleTypeAliasDeclaration = 63,
RuleExternalBuiltin = 64,
RuleExternalMacro = 65,
RuleExternalRuntime = 66,
RuleBuiltinDeclaration = 67,
RuleGenericSpecialization = 68,
RuleMacroDeclaration = 69,
RuleExternConstDeclaration = 70,
RuleConstDeclaration = 71,
RuleStructDeclaration = 72,
RuleDeclaration = 73,
RuleModuleDeclaration = 74,
RuleFile = 75
};
explicit TorqueParser(antlr4::TokenStream* input);
@ -207,6 +213,8 @@ class TorqueParser : public antlr4::Parser {
class IncrementDecrementContext;
class AssignmentContext;
class AssignmentExpressionContext;
class StructExpressionContext;
class FunctionPointerExpressionContext;
class PrimaryExpressionContext;
class ForInitializationContext;
class ForLoopContext;
@ -235,6 +243,8 @@ class TorqueParser : public antlr4::Parser {
class StatementScopeContext;
class StatementBlockContext;
class HelperBodyContext;
class FieldDeclarationContext;
class FieldListDeclarationContext;
class ExtendsDeclarationContext;
class GeneratesDeclarationContext;
class ConstexprDeclarationContext;
@ -248,6 +258,7 @@ class TorqueParser : public antlr4::Parser {
class MacroDeclarationContext;
class ExternConstDeclarationContext;
class ConstDeclarationContext;
class StructDeclarationContext;
class DeclarationContext;
class ModuleDeclarationContext;
class FileContext;
@ -658,9 +669,9 @@ class TorqueParser : public antlr4::Parser {
size_t invokingState);
size_t getRuleIndex() const override;
antlr4::tree::TerminalNode* IDENTIFIER();
GenericSpecializationTypeListContext* genericSpecializationTypeList();
LocationExpressionContext* locationExpression();
PrimaryExpressionContext* primaryExpression();
ExpressionContext* expression();
LocationExpressionContext* locationExpression();
void enterRule(antlr4::tree::ParseTreeListener* listener) override;
void exitRule(antlr4::tree::ParseTreeListener* listener) override;
@ -711,7 +722,7 @@ class TorqueParser : public antlr4::Parser {
AssignmentExpressionContext(antlr4::ParserRuleContext* parent,
size_t invokingState);
size_t getRuleIndex() const override;
PrimaryExpressionContext* primaryExpression();
FunctionPointerExpressionContext* functionPointerExpression();
AssignmentContext* assignment();
void enterRule(antlr4::tree::ParseTreeListener* listener) override;
@ -722,12 +733,47 @@ class TorqueParser : public antlr4::Parser {
AssignmentExpressionContext* assignmentExpression();
class StructExpressionContext : public antlr4::ParserRuleContext {
public:
StructExpressionContext(antlr4::ParserRuleContext* parent,
size_t invokingState);
size_t getRuleIndex() const override;
antlr4::tree::TerminalNode* IDENTIFIER();
std::vector<ExpressionContext*> expression();
ExpressionContext* expression(size_t i);
void enterRule(antlr4::tree::ParseTreeListener* listener) override;
void exitRule(antlr4::tree::ParseTreeListener* listener) override;
antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor* visitor) override;
};
StructExpressionContext* structExpression();
class FunctionPointerExpressionContext : public antlr4::ParserRuleContext {
public:
FunctionPointerExpressionContext(antlr4::ParserRuleContext* parent,
size_t invokingState);
size_t getRuleIndex() const override;
PrimaryExpressionContext* primaryExpression();
antlr4::tree::TerminalNode* IDENTIFIER();
GenericSpecializationTypeListContext* genericSpecializationTypeList();
void enterRule(antlr4::tree::ParseTreeListener* listener) override;
void exitRule(antlr4::tree::ParseTreeListener* listener) override;
antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor* visitor) override;
};
FunctionPointerExpressionContext* functionPointerExpression();
class PrimaryExpressionContext : public antlr4::ParserRuleContext {
public:
PrimaryExpressionContext(antlr4::ParserRuleContext* parent,
size_t invokingState);
size_t getRuleIndex() const override;
HelperCallContext* helperCall();
StructExpressionContext* structExpression();
antlr4::tree::TerminalNode* DECIMAL_LITERAL();
antlr4::tree::TerminalNode* STRING_LITERAL();
ExpressionContext* expression();
@ -1196,6 +1242,38 @@ class TorqueParser : public antlr4::Parser {
HelperBodyContext* helperBody();
class FieldDeclarationContext : public antlr4::ParserRuleContext {
public:
FieldDeclarationContext(antlr4::ParserRuleContext* parent,
size_t invokingState);
size_t getRuleIndex() const override;
antlr4::tree::TerminalNode* IDENTIFIER();
TypeContext* type();
void enterRule(antlr4::tree::ParseTreeListener* listener) override;
void exitRule(antlr4::tree::ParseTreeListener* listener) override;
antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor* visitor) override;
};
FieldDeclarationContext* fieldDeclaration();
class FieldListDeclarationContext : public antlr4::ParserRuleContext {
public:
FieldListDeclarationContext(antlr4::ParserRuleContext* parent,
size_t invokingState);
size_t getRuleIndex() const override;
std::vector<FieldDeclarationContext*> fieldDeclaration();
FieldDeclarationContext* fieldDeclaration(size_t i);
void enterRule(antlr4::tree::ParseTreeListener* listener) override;
void exitRule(antlr4::tree::ParseTreeListener* listener) override;
antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor* visitor) override;
};
FieldListDeclarationContext* fieldListDeclaration();
class ExtendsDeclarationContext : public antlr4::ParserRuleContext {
public:
ExtendsDeclarationContext(antlr4::ParserRuleContext* parent,
@ -1437,10 +1515,27 @@ class TorqueParser : public antlr4::Parser {
ConstDeclarationContext* constDeclaration();
class StructDeclarationContext : public antlr4::ParserRuleContext {
public:
StructDeclarationContext(antlr4::ParserRuleContext* parent,
size_t invokingState);
size_t getRuleIndex() const override;
antlr4::tree::TerminalNode* IDENTIFIER();
FieldListDeclarationContext* fieldListDeclaration();
void enterRule(antlr4::tree::ParseTreeListener* listener) override;
void exitRule(antlr4::tree::ParseTreeListener* listener) override;
antlrcpp::Any accept(antlr4::tree::ParseTreeVisitor* visitor) override;
};
StructDeclarationContext* structDeclaration();
class DeclarationContext : public antlr4::ParserRuleContext {
public:
DeclarationContext(antlr4::ParserRuleContext* parent, size_t invokingState);
size_t getRuleIndex() const override;
StructDeclarationContext* structDeclaration();
TypeDeclarationContext* typeDeclaration();
TypeAliasDeclarationContext* typeAliasDeclaration();
BuiltinDeclarationContext* builtinDeclaration();

View File

@ -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;

View File

@ -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);

View File

@ -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())

View File

@ -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; \

View File

@ -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) {

View File

@ -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.");

View File

@ -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));
}
}
}

View File

@ -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();

View File

@ -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));

View File

@ -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,

View File

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <algorithm>
#include "src/torque/implementation-visitor.h"
#include "src/torque/parameter-difference.h"
@ -188,6 +190,18 @@ void ImplementationVisitor::Visit(ConstDeclaration* decl) {
source_out() << "}\n\n";
}
void ImplementationVisitor::Visit(StructDeclaration* decl) {
header_out() << " struct " << decl->name << " {\n";
const StructType* struct_type =
static_cast<const StructType*>(declarations()->LookupType(decl->name));
for (auto& field : struct_type->fields()) {
header_out() << " " << field.type->GetGeneratedTypeName();
header_out() << " " << field.name << ";\n";
}
header_out() << " } "
<< ";\n";
}
void ImplementationVisitor::Visit(TorqueMacroDeclaration* decl,
const Signature& sig, Statement* body) {
Signature signature = MakeSignature(decl->signature.get());
@ -246,7 +260,8 @@ void ImplementationVisitor::Visit(TorqueMacroDeclaration* decl,
if (result_var != nullptr) {
GenerateIndent();
source_out() << "return "
<< VisitResult(result_var->type(), result_var).RValue()
<< RValueFlattenStructs(
VisitResult(result_var->type(), result_var))
<< ";" << std::endl;
}
source_out() << "}" << std::endl << std::endl;
@ -335,7 +350,7 @@ VisitResult ImplementationVisitor::Visit(ConditionalExpression* expr) {
source_out() << "" << std::endl;
left = Visit(expr->if_true);
GenerateIndent();
source_out() << "return " << left.RValue() << ";" << std::endl;
source_out() << "return " << RValueFlattenStructs(left) << ";" << std::endl;
}
source_out() << ";" << std::endl;
GenerateIndent();
@ -345,7 +360,8 @@ VisitResult ImplementationVisitor::Visit(ConditionalExpression* expr) {
source_out() << "" << std::endl;
right = Visit(expr->if_false);
GenerateIndent();
source_out() << "return " << right.RValue() << ";" << std::endl;
source_out() << "return " << RValueFlattenStructs(right) << ";"
<< std::endl;
}
source_out() << ";" << std::endl;
@ -397,7 +413,7 @@ VisitResult ImplementationVisitor::Visit(LogicalOrExpression* expr) {
if (left_result.type()->IsBool()) {
Label* true_label = declarations()->LookupLabel(kTrueLabelName);
GenerateIndent();
source_out() << "GotoIf(" << left_result.RValue() << ", "
source_out() << "GotoIf(" << RValueFlattenStructs(left_result) << ", "
<< true_label->generated() << ");" << std::endl;
} else if (!left_result.type()->IsConstexprBool()) {
GenerateLabelBind(false_label);
@ -412,9 +428,9 @@ VisitResult ImplementationVisitor::Visit(LogicalOrExpression* expr) {
ReportError(stream.str());
}
if (left_result.type()->IsConstexprBool()) {
return VisitResult(left_result.type(), std::string("(") +
left_result.RValue() + " || " +
right_result.RValue() + ")");
return VisitResult(left_result.type(),
std::string("(") + RValueFlattenStructs(left_result) +
" || " + RValueFlattenStructs(right_result) + ")");
} else {
return right_result;
}
@ -430,7 +446,7 @@ VisitResult ImplementationVisitor::Visit(LogicalAndExpression* expr) {
if (left_result.type()->IsBool()) {
Label* false_label = declarations()->LookupLabel(kFalseLabelName);
GenerateIndent();
source_out() << "GotoIfNot(" << left_result.RValue() << ", "
source_out() << "GotoIfNot(" << RValueFlattenStructs(left_result) << ", "
<< false_label->generated() << ");" << std::endl;
} else if (!left_result.type()->IsConstexprBool()) {
GenerateLabelBind(true_label);
@ -445,9 +461,9 @@ VisitResult ImplementationVisitor::Visit(LogicalAndExpression* expr) {
ReportError(stream.str());
}
if (left_result.type()->IsConstexprBool()) {
return VisitResult(left_result.type(), std::string("(") +
left_result.RValue() + " && " +
right_result.RValue() + ")");
return VisitResult(left_result.type(),
std::string("(") + RValueFlattenStructs(left_result) +
" && " + RValueFlattenStructs(right_result) + ")");
} else {
return right_result;
}
@ -591,7 +607,8 @@ const Type* ImplementationVisitor::Visit(IfStatement* stmt) {
const Type* right_result = TypeOracle::GetVoidType();
{
GenerateIndent();
source_out() << "if ((" << expression_result.RValue() << ")) ";
source_out() << "if ((" << RValueFlattenStructs(expression_result)
<< ")) ";
ScopedIndent indent(this, false);
source_out() << std::endl;
left_result = Visit(stmt->if_true);
@ -807,11 +824,12 @@ const Type* ImplementationVisitor::Visit(ReturnStatement* stmt) {
} else if (current_callable->IsBuiltin()) {
if (Builtin::cast(current_callable)->IsVarArgsJavaScript()) {
GenerateIndent();
source_out() << "arguments->PopAndReturn(" << return_result.RValue()
<< ");" << std::endl;
source_out() << "arguments->PopAndReturn("
<< RValueFlattenStructs(return_result) << ");"
<< std::endl;
} else {
GenerateIndent();
source_out() << "Return(" << return_result.RValue() << ");"
source_out() << "Return(" << RValueFlattenStructs(return_result) << ");"
<< std::endl;
}
} else {
@ -1070,8 +1088,11 @@ void ImplementationVisitor::GenerateFunctionDeclaration(
// Quite a hack here. Make sure that TNode is namespace qualified if the
// macro/constant name is also qualified.
std::string return_type_name(signature.return_type->GetGeneratedTypeName());
if (macro_prefix != "" && (return_type_name.length() > 5) &&
(return_type_name.substr(0, 5) == "TNode")) {
if (const StructType* struct_type =
StructType::DynamicCast(signature.return_type)) {
o << GetDSLAssemblerName(struct_type->module()) << "::";
} else if (macro_prefix != "" && (return_type_name.length() > 5) &&
(return_type_name.substr(0, 5) == "TNode")) {
o << "compiler::";
}
o << return_type_name;
@ -1220,21 +1241,33 @@ Callable* ImplementationVisitor::LookupCall(const std::string& name,
return result;
}
void ImplementationVisitor::GetFlattenedStructsVars(
const Variable* base, std::set<const Variable*>& vars) {
const Type* type = base->type();
if (base->IsConst()) return;
if (type->IsStructType()) {
const StructType* struct_type = StructType::cast(type);
for (auto& field : struct_type->fields()) {
std::string field_var_name = base->name() + "." + field.name;
GetFlattenedStructsVars(
Variable::cast(declarations()->LookupValue(field_var_name)), vars);
}
} else {
vars.insert(base);
}
}
void ImplementationVisitor::GenerateChangedVarsFromControlSplit(AstNode* node) {
const std::set<const Variable*>& changed_vars =
global_context_.GetControlSplitChangedVariables(
node, declarations()->GetCurrentSpecializationTypeNamesVector());
source_out() << "{";
bool first = true;
std::set<const Variable*> flattened_vars;
for (auto v : changed_vars) {
if (v->IsConst()) continue;
if (first) {
first = false;
} else {
source_out() << ", ";
}
source_out() << v->value();
GetFlattenedStructsVars(v, flattened_vars);
}
source_out() << "{";
PrintCommaSeparatedList(source_out(), flattened_vars,
[&](const Variable* v) { return v->value(); });
source_out() << "}";
}
@ -1254,12 +1287,42 @@ const Type* ImplementationVisitor::GetCommonType(const Type* left,
VisitResult ImplementationVisitor::GenerateCopy(const VisitResult& to_copy) {
std::string temp = GenerateNewTempVariable(to_copy.type());
source_out() << to_copy.RValue() << ";" << std::endl;
source_out() << RValueFlattenStructs(to_copy) << ";" << std::endl;
GenerateIndent();
source_out() << "USE(" << temp << ");" << std::endl;
return VisitResult(to_copy.type(), temp);
}
VisitResult ImplementationVisitor::Visit(StructExpression* decl) {
const Type* raw_type = declarations()->LookupType(decl->name);
if (!raw_type->IsStructType()) {
std::stringstream s;
s << decl->name << " is not a struct but used like one ";
ReportError(s.str());
}
const StructType* struct_type = StructType::cast(raw_type);
if (struct_type->fields().size() != decl->expressions.size()) {
std::stringstream s;
s << "initializer count mismatch for struct " << decl->name << " (expected "
<< struct_type->fields().size() << ", found " << decl->expressions.size()
<< ")";
ReportError(s.str());
}
std::vector<VisitResult> expression_results;
for (auto& field : struct_type->fields()) {
VisitResult value = Visit(decl->expressions[expression_results.size()]);
value = GenerateImplicitConvert(field.type, value);
expression_results.push_back(value);
}
std::string result_var_name = GenerateNewTempVariable(struct_type);
source_out() << "{";
PrintCommaSeparatedList(
source_out(), expression_results,
[&](const VisitResult& result) { return RValueFlattenStructs(result); });
source_out() << "};\n";
return VisitResult(struct_type, result_var_name);
}
LocationReference ImplementationVisitor::GetLocationReference(
LocationExpression* location) {
switch (location->kind) {
@ -1276,6 +1339,47 @@ LocationReference ImplementationVisitor::GetLocationReference(
}
}
LocationReference ImplementationVisitor::GetLocationReference(
FieldAccessExpression* expr) {
VisitResult result = Visit(expr->object);
if (result.type()->IsStructType()) {
if (result.declarable()) {
return LocationReference(
declarations()->LookupValue((*result.declarable())->name() + "." +
expr->field),
{}, {});
} else {
return LocationReference(
nullptr,
VisitResult(result.type(), result.RValue() + "." + expr->field), {});
}
}
return LocationReference(nullptr, result, {});
}
std::string ImplementationVisitor::RValueFlattenStructs(VisitResult result) {
if (result.declarable()) {
const Value* value = *result.declarable();
const Type* type = value->type();
if (const StructType* struct_type = StructType::DynamicCast(type)) {
std::stringstream s;
s << struct_type->name() << "{";
PrintCommaSeparatedList(
s, struct_type->fields(), [&](const NameAndType& field) {
std::string field_declaration = value->name() + "." + field.name;
Variable* field_variable =
Variable::cast(declarations()->LookupValue(field_declaration));
return RValueFlattenStructs(
VisitResult(field_variable->type(), field_variable));
});
s << "}";
return s.str();
}
}
return result.RValue();
}
VisitResult ImplementationVisitor::GenerateFetchFromLocation(
LocationExpression* location, LocationReference reference) {
switch (location->kind) {
@ -1293,28 +1397,77 @@ VisitResult ImplementationVisitor::GenerateFetchFromLocation(
}
}
VisitResult ImplementationVisitor::GenerateFetchFromLocation(
FieldAccessExpression* expr, LocationReference reference) {
const Type* type = reference.base.type();
if (reference.value != nullptr) {
return GenerateFetchFromLocation(reference);
} else if (const StructType* struct_type = StructType::DynamicCast(type)) {
auto& fields = struct_type->fields();
auto i = std::find_if(
fields.begin(), fields.end(),
[&](const NameAndType& f) { return f.name == expr->field; });
if (i == fields.end()) {
std::stringstream s;
s << "\"" << expr->field << "\" is not a field of struct type \""
<< struct_type->name() << "\"";
ReportError(s.str());
}
return VisitResult(i->type, reference.base.RValue());
} else {
Arguments arguments;
arguments.parameters = {reference.base};
return GenerateCall(std::string(".") + expr->field, arguments);
}
}
void ImplementationVisitor::GenerateAssignToVariable(Variable* var,
VisitResult value) {
VisitResult casted_value = GenerateImplicitConvert(var->type(), value);
GenerateIndent();
VisitResult variable_result = {var->type(), var};
source_out() << variable_result.LValue() << " = " << casted_value.RValue()
<< ";\n";
if (var->type()->IsStructType()) {
if (value.type() != var->type()) {
std::stringstream s;
s << "incompatable assignment from type " << *value.type() << " to "
<< *var->type();
ReportError(s.str());
}
const StructType* struct_type = StructType::cast(var->type());
for (auto& field : struct_type->fields()) {
std::string field_declaration = var->name() + "." + field.name;
Variable* field_variable =
Variable::cast(declarations()->LookupValue(field_declaration));
if (value.declarable() && (*value.declarable())->IsVariable()) {
Variable* source_field = Variable::cast(declarations()->LookupValue(
Variable::cast((*value.declarable()))->name() + "." + field.name));
GenerateAssignToVariable(
field_variable, VisitResult{source_field->type(), source_field});
} else {
GenerateAssignToVariable(
field_variable, VisitResult{field_variable->type(),
value.RValue() + "." + field.name});
}
}
} else {
VisitResult casted_value = GenerateImplicitConvert(var->type(), value);
GenerateIndent();
VisitResult var_value = {var->type(), var};
source_out() << var_value.LValue() << " = "
<< RValueFlattenStructs(casted_value) << ";" << std::endl;
}
var->Define();
}
void ImplementationVisitor::GenerateAssignToLocation(
LocationExpression* location, const LocationReference& reference,
VisitResult assignment_value) {
if (IdentifierExpression::cast(location)) {
if (reference.value != nullptr) {
Value* value = reference.value;
if (value->IsConst()) {
Variable* var = Variable::cast(value);
if (var->IsConst()) {
std::stringstream s;
s << "\"" << value->name()
s << "\"" << var->name()
<< "\" is declared const (maybe implicitly) and cannot be assigned to";
ReportError(s.str());
}
Variable* var = Variable::cast(value);
GenerateAssignToVariable(var, assignment_value);
} else if (auto access = FieldAccessExpression::cast(location)) {
GenerateCall(std::string(".") + access->field + "=",
@ -1326,6 +1479,36 @@ void ImplementationVisitor::GenerateAssignToLocation(
}
}
void ImplementationVisitor::GenerateVariableDeclaration(const Variable* var) {
const Type* var_type = var->type();
if (var_type->IsStructType()) {
const StructType* struct_type = StructType::cast(var_type);
for (auto& field : struct_type->fields()) {
GenerateVariableDeclaration(Variable::cast(
declarations()->LookupValue(var->name() + "." + field.name)));
}
} else {
std::string value = var->value();
GenerateIndent();
if (var_type->IsConstexpr()) {
source_out() << var_type->GetGeneratedTypeName();
source_out() << " " << value << "_impl;" << std::endl;
} else if (var->IsConst()) {
source_out() << "TNode<" << var->type()->GetGeneratedTNodeTypeName();
source_out() << "> " << var->value() << "_impl;\n";
} else {
source_out() << "TVARIABLE(";
source_out() << var_type->GetGeneratedTNodeTypeName();
source_out() << ", " << value << "_impl);" << std::endl;
}
GenerateIndent();
source_out() << "auto " << value << " = &" << value << "_impl;"
<< std::endl;
GenerateIndent();
source_out() << "USE(" << value << ");" << std::endl;
}
}
Variable* ImplementationVisitor::GenerateVariableDeclaration(
AstNode* node, const std::string& name,
const base::Optional<const Type*>& type,
@ -1344,24 +1527,7 @@ Variable* ImplementationVisitor::GenerateVariableDeclaration(
node, declarations()->GetCurrentSpecializationTypeNamesVector(),
variable);
}
GenerateIndent();
if (variable->type()->IsConstexpr()) {
source_out() << variable->type()->GetGeneratedTypeName();
source_out() << " " << variable->value() << "_impl;\n";
} else if (variable->IsConst()) {
source_out() << "TNode<" << variable->type()->GetGeneratedTNodeTypeName();
source_out() << "> " << variable->value() << "_impl;\n";
} else {
source_out() << "TVARIABLE(";
source_out() << variable->type()->GetGeneratedTNodeTypeName();
source_out() << ", " << variable->value() << "_impl);\n";
}
GenerateIndent();
source_out() << "auto " << variable->value() << " = &" << variable->value()
<< "_impl;\n";
GenerateIndent();
source_out() << "USE(" << variable->value() << ");\n";
GenerateVariableDeclaration(variable);
if (initialization) {
GenerateAssignToVariable(variable, *initialization);
}
@ -1431,7 +1597,7 @@ VisitResult ImplementationVisitor::GeneratePointerCall(
const Type* to_type = type->parameter_types()[current];
VisitResult result =
GenerateImplicitConvert(to_type, arguments.parameters[current]);
variables.push_back(result.RValue());
variables.push_back(RValueFlattenStructs(result));
}
std::string result_variable_name;
@ -1439,10 +1605,15 @@ VisitResult ImplementationVisitor::GeneratePointerCall(
if (no_result) {
GenerateIndent();
} else {
result_variable_name = GenerateNewTempVariable(type->return_type());
source_out() << "UncheckedCast<";
source_out() << type->return_type()->GetGeneratedTNodeTypeName();
source_out() << ">(";
const Type* return_type = type->return_type();
result_variable_name = GenerateNewTempVariable(return_type);
if (return_type->IsStructType()) {
source_out() << "(";
} else {
source_out() << "UncheckedCast<";
source_out() << type->return_type()->GetGeneratedTNodeTypeName();
source_out() << ">(";
}
}
Builtin* example_builtin =
@ -1460,7 +1631,7 @@ VisitResult ImplementationVisitor::GeneratePointerCall(
}
source_out() << "Builtins::CallableFor(isolate(), Builtins::k"
<< example_builtin->name() << ").descriptor(), "
<< callee_result.RValue() << ", ";
<< RValueFlattenStructs(callee_result) << ", ";
size_t total_parameters = 0;
for (size_t i = 0; i < arguments.parameters.size(); ++i) {
@ -1499,7 +1670,7 @@ VisitResult ImplementationVisitor::GenerateCall(
: callable->signature().types()[current];
VisitResult result =
GenerateImplicitConvert(to_type, arguments.parameters[current]);
variables.push_back(result.RValue());
variables.push_back(RValueFlattenStructs(result));
}
std::string result_variable_name;
@ -1508,9 +1679,13 @@ VisitResult ImplementationVisitor::GenerateCall(
} else {
result_variable_name = GenerateNewTempVariable(result_type);
if (!result_type->IsConstexpr()) {
source_out() << "UncheckedCast<";
source_out() << result_type->GetGeneratedTNodeTypeName();
source_out() << ">(";
if (result_type->IsStructType()) {
source_out() << "(";
} else {
source_out() << "UncheckedCast<";
source_out() << result_type->GetGeneratedTNodeTypeName();
source_out() << ">(";
}
}
}
if (callable->IsBuiltin()) {
@ -1663,7 +1838,7 @@ VisitResult ImplementationVisitor::Visit(CallExpression* expr,
}
if (!result.type()->IsVoidOrNever()) {
GenerateIndent();
source_out() << "USE(" << result.RValue() << ");" << std::endl;
source_out() << "USE(" << RValueFlattenStructs(result) << ");" << std::endl;
}
if (is_tailcall) {
result = {TypeOracle::GetNeverType(), ""};
@ -1695,7 +1870,7 @@ void ImplementationVisitor::GenerateBranch(const VisitResult& condition,
Label* true_label,
Label* false_label) {
GenerateIndent();
source_out() << "Branch(" << condition.RValue() << ", "
source_out() << "Branch(" << RValueFlattenStructs(condition) << ", "
<< true_label->generated() << ", " << false_label->generated()
<< ");" << std::endl;
}

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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()};
}
}