add owning method to statements

create common keyword statement class
This commit is contained in:
Dave Holoway
2020-06-25 11:43:53 +01:00
parent b0a2475696
commit f67c03bb34
20 changed files with 125 additions and 112 deletions

View File

@@ -62,8 +62,8 @@ const { TryStatement } = require("./statementtypes/TryStatement");
const { WhileStatement } = require("./statementtypes/WhileStatement"); const { WhileStatement } = require("./statementtypes/WhileStatement");
/** /**
* @typedef {SourceMethod|SourceConstructor|SourceInitialiser} SourceMC * @typedef {import('./source-types').SourceMethodLike} SourceMethodLike
* @typedef {SourceType|SourceMC} Scope * @typedef {SourceType|SourceMethodLike} Scope
*/ */
@@ -394,7 +394,7 @@ function addLocals(tokens, mdecls, new_locals) {
/** /**
* @param {TokenList} tokens * @param {TokenList} tokens
* @param {MethodDeclarations} mdecls * @param {MethodDeclarations} mdecls
* @param {SourceMC} method * @param {SourceMethodLike} method
* @param {ResolvedImport[]} imports * @param {ResolvedImport[]} imports
* @param {Map<string,CEIType>} typemap * @param {Map<string,CEIType>} typemap
* @returns {Statement} * @returns {Statement}
@@ -419,7 +419,7 @@ function statement(tokens, mdecls, method, imports, typemap) {
const locals = var_ident_list(modifiers, type, null, tokens, mdecls, method, imports, typemap) const locals = var_ident_list(modifiers, type, null, tokens, mdecls, method, imports, typemap)
addLocals(tokens, mdecls, locals); addLocals(tokens, mdecls, locals);
semicolon(tokens); semicolon(tokens);
return new LocalDeclStatement(locals); return new LocalDeclStatement(method, locals);
} }
switch(tokens.current.kind) { switch(tokens.current.kind) {
@@ -442,9 +442,9 @@ function statement(tokens, mdecls, method, imports, typemap) {
const exp_or_vardecl = expression_or_var_decl(tokens, mdecls, method, imports, typemap); const exp_or_vardecl = expression_or_var_decl(tokens, mdecls, method, imports, typemap);
if (Array.isArray(exp_or_vardecl)) { if (Array.isArray(exp_or_vardecl)) {
addLocals(tokens, mdecls, exp_or_vardecl); addLocals(tokens, mdecls, exp_or_vardecl);
s = new LocalDeclStatement(exp_or_vardecl); s = new LocalDeclStatement(method, exp_or_vardecl);
} else { } else {
s = new ExpressionStatement(exp_or_vardecl); s = new ExpressionStatement(method, exp_or_vardecl);
} }
semicolon(tokens); semicolon(tokens);
return s; return s;
@@ -459,21 +459,20 @@ function statement(tokens, mdecls, method, imports, typemap) {
case 'open-bracket': case 'open-bracket':
case 'new-operator': case 'new-operator':
const e = expression(tokens, mdecls, method, imports, typemap); const e = expression(tokens, mdecls, method, imports, typemap);
s = new ExpressionStatement(e); s = new ExpressionStatement(method, e);
semicolon(tokens); semicolon(tokens);
return s; return s;
} }
switch(tokens.current.value) { switch(tokens.current.value) {
case ';': case ';':
tokens.inc(); tokens.inc();
return new EmptyStatement(); return new EmptyStatement(method);
case '{': case '{':
return statementBlock(tokens, mdecls, method, imports, typemap); return statementBlock(tokens, mdecls, method, imports, typemap);
case '}': case '}':
return new EmptyStatement(); return new EmptyStatement(method);
} }
tokens.inc(); return new InvalidStatement(method, tokens.consume());
return new InvalidStatement(tokens.previous);
} }
/** /**
@@ -875,12 +874,12 @@ function enumValueList(type, tokens, imports, typemap) {
/** /**
* @param {TokenList} tokens * @param {TokenList} tokens
* @param {MethodDeclarations} mdecls * @param {MethodDeclarations} mdecls
* @param {SourceMC} method * @param {SourceMethodLike} method
* @param {ResolvedImport[]} imports * @param {ResolvedImport[]} imports
* @param {Map<string,CEIType>} typemap * @param {Map<string,CEIType>} typemap
*/ */
function statementBlock(tokens, mdecls, method, imports, typemap) { function statementBlock(tokens, mdecls, method, imports, typemap) {
const block = new Block(tokens.current); const block = new Block(method, tokens.current);
tokens.expectValue('{'); tokens.expectValue('{');
mdecls.pushScope(); mdecls.pushScope();
while (!tokens.isValue('}')) { while (!tokens.isValue('}')) {
@@ -904,7 +903,7 @@ function semicolon(tokens) {
/** /**
* @param {TokenList} tokens * @param {TokenList} tokens
* @param {MethodDeclarations} mdecls * @param {MethodDeclarations} mdecls
* @param {SourceMC} method * @param {SourceMethodLike} method
* @param {ResolvedImport[]} imports * @param {ResolvedImport[]} imports
* @param {Map<string,CEIType>} typemap * @param {Map<string,CEIType>} typemap
*/ */
@@ -912,8 +911,7 @@ function statementKeyword(tokens, mdecls, method, imports, typemap) {
let s; let s;
switch (tokens.current.value) { switch (tokens.current.value) {
case 'if': case 'if':
tokens.inc(); s = new IfStatement(method, tokens.consume());
s = new IfStatement();
s.test = bracketedTest(tokens, mdecls, method, imports, typemap); s.test = bracketedTest(tokens, mdecls, method, imports, typemap);
s.statement = statement(tokens, mdecls, method, imports, typemap); s.statement = statement(tokens, mdecls, method, imports, typemap);
if (tokens.isValue('else')) { if (tokens.isValue('else')) {
@@ -921,74 +919,64 @@ function statementKeyword(tokens, mdecls, method, imports, typemap) {
} }
break; break;
case 'while': case 'while':
tokens.inc(); s = new WhileStatement(method, tokens.consume());
s = new WhileStatement();
s.test = bracketedTest(tokens, mdecls, method, imports, typemap); s.test = bracketedTest(tokens, mdecls, method, imports, typemap);
s.statement = statement(tokens, mdecls, method, imports, typemap); s.statement = statement(tokens, mdecls, method, imports, typemap);
break; break;
case 'break': case 'break':
s = new BreakStatement(tokens.consume()); s = new BreakStatement(method, tokens.consume());
s.target = tokens.getIfKind('ident'); s.target = tokens.getIfKind('ident');
semicolon(tokens); semicolon(tokens);
break; break;
case 'continue': case 'continue':
s = new ContinueStatement(tokens.consume()); s = new ContinueStatement(method, tokens.consume());
s.target = tokens.getIfKind('ident'); s.target = tokens.getIfKind('ident');
semicolon(tokens); semicolon(tokens);
break; break;
case 'switch': case 'switch':
tokens.inc(); s = new SwitchStatement(method, tokens.consume());
s = new SwitchStatement();
switchBlock(s, tokens, mdecls, method, imports, typemap); switchBlock(s, tokens, mdecls, method, imports, typemap);
break; break;
case 'do': case 'do':
tokens.inc(); s = new DoStatement(method, tokens.consume());
s = new DoStatement();
s.block = statementBlock(tokens, mdecls, method, imports, typemap); s.block = statementBlock(tokens, mdecls, method, imports, typemap);
tokens.expectValue('while'); tokens.expectValue('while');
s.test = bracketedTest(tokens, mdecls, method, imports, typemap); s.test = bracketedTest(tokens, mdecls, method, imports, typemap);
semicolon(tokens); semicolon(tokens);
break; break;
case 'try': case 'try':
tokens.inc(); s = new TryStatement(method, tokens.consume());
s = new TryStatement();
tryStatement(s, tokens, mdecls, method, imports, typemap); tryStatement(s, tokens, mdecls, method, imports, typemap);
break; break;
case 'return': case 'return':
s = new ReturnStatement(tokens.current); s = new ReturnStatement(method, tokens.consume());
tokens.inc();
s.expression = isExpressionStart(tokens.current) ? expression(tokens, mdecls, method, imports, typemap) : null; s.expression = isExpressionStart(tokens.current) ? expression(tokens, mdecls, method, imports, typemap) : null;
semicolon(tokens); semicolon(tokens);
break; break;
case 'throw': case 'throw':
tokens.inc(); s = new ThrowStatement(method, tokens.consume());
s = new ThrowStatement();
if (!tokens.isValue(';')) { if (!tokens.isValue(';')) {
s.expression = isExpressionStart(tokens.current) ? expression(tokens, mdecls, method, imports, typemap) : null; s.expression = isExpressionStart(tokens.current) ? expression(tokens, mdecls, method, imports, typemap) : null;
semicolon(tokens); semicolon(tokens);
} }
break; break;
case 'for': case 'for':
tokens.inc(); s = new ForStatement(method, tokens.consume());
s = new ForStatement();
mdecls.pushScope(); mdecls.pushScope();
forStatement(s, tokens, mdecls, method, imports, typemap); forStatement(s, tokens, mdecls, method, imports, typemap);
mdecls.popScope(); mdecls.popScope();
break; break;
case 'synchronized': case 'synchronized':
tokens.inc(); s = new SynchronizedStatement(method, tokens.consume());
s = new SynchronizedStatement();
synchronizedStatement(s, tokens, mdecls, method, imports, typemap); synchronizedStatement(s, tokens, mdecls, method, imports, typemap);
break; break;
case 'assert': case 'assert':
tokens.inc(); s = new AssertStatement(method, tokens.consume());
s = new AssertStatement();
assertStatement(s, tokens, mdecls, method, imports, typemap); assertStatement(s, tokens, mdecls, method, imports, typemap);
semicolon(tokens); semicolon(tokens);
break; break;
default: default:
s = new InvalidStatement(tokens.current); s = new InvalidStatement(method, tokens.consume());
tokens.inc();
break; break;
} }
return s; return s;
@@ -1012,7 +1000,7 @@ function bracketedTest(tokens, mdecls, scope, imports, typemap) {
* @param {TryStatement} s * @param {TryStatement} s
* @param {TokenList} tokens * @param {TokenList} tokens
* @param {MethodDeclarations} mdecls * @param {MethodDeclarations} mdecls
* @param {SourceMC} method * @param {SourceMethodLike} method
* @param {ResolvedImport[]} imports * @param {ResolvedImport[]} imports
* @param {Map<string,CEIType>} typemap * @param {Map<string,CEIType>} typemap
*/ */
@@ -1048,7 +1036,7 @@ function tryStatement(s, tokens, mdecls, method, imports, typemap) {
* @param {ForStatement} s * @param {ForStatement} s
* @param {TokenList} tokens * @param {TokenList} tokens
* @param {MethodDeclarations} mdecls * @param {MethodDeclarations} mdecls
* @param {SourceMC} method * @param {SourceMethodLike} method
* @param {ResolvedImport[]} imports * @param {ResolvedImport[]} imports
* @param {Map<string,CEIType>} typemap * @param {Map<string,CEIType>} typemap
*/ */
@@ -1084,7 +1072,7 @@ function forStatement(s, tokens, mdecls, method, imports, typemap) {
* @param {ForStatement} s * @param {ForStatement} s
* @param {TokenList} tokens * @param {TokenList} tokens
* @param {MethodDeclarations} mdecls * @param {MethodDeclarations} mdecls
* @param {SourceMC} method * @param {SourceMethodLike} method
* @param {ResolvedImport[]} imports * @param {ResolvedImport[]} imports
* @param {Map<string,CEIType>} typemap * @param {Map<string,CEIType>} typemap
*/ */
@@ -1101,7 +1089,7 @@ function enhancedFor(s, tokens, mdecls, method, imports, typemap) {
* @param {SynchronizedStatement} s * @param {SynchronizedStatement} s
* @param {TokenList} tokens * @param {TokenList} tokens
* @param {MethodDeclarations} mdecls * @param {MethodDeclarations} mdecls
* @param {SourceMC} method * @param {SourceMethodLike} method
* @param {ResolvedImport[]} imports * @param {ResolvedImport[]} imports
* @param {Map<string,CEIType>} typemap * @param {Map<string,CEIType>} typemap
*/ */
@@ -1116,7 +1104,7 @@ function synchronizedStatement(s, tokens, mdecls, method, imports, typemap) {
* @param {AssertStatement} s * @param {AssertStatement} s
* @param {TokenList} tokens * @param {TokenList} tokens
* @param {MethodDeclarations} mdecls * @param {MethodDeclarations} mdecls
* @param {SourceMC} method * @param {SourceMethodLike} method
* @param {ResolvedImport[]} imports * @param {ResolvedImport[]} imports
* @param {Map<string,CEIType>} typemap * @param {Map<string,CEIType>} typemap
*/ */
@@ -1131,7 +1119,7 @@ function assertStatement(s, tokens, mdecls, method, imports, typemap) {
* @param {TryStatement} s * @param {TryStatement} s
* @param {TokenList} tokens * @param {TokenList} tokens
* @param {MethodDeclarations} mdecls * @param {MethodDeclarations} mdecls
* @param {SourceMC} method * @param {SourceMethodLike} method
* @param {ResolvedImport[]} imports * @param {ResolvedImport[]} imports
* @param {Map<string,CEIType>} typemap * @param {Map<string,CEIType>} typemap
*/ */
@@ -1184,7 +1172,7 @@ function catchFinallyBlocks(s, tokens, mdecls, method, imports, typemap) {
/** /**
* @param {TokenList} tokens * @param {TokenList} tokens
* @param {MethodDeclarations} mdecls * @param {MethodDeclarations} mdecls
* @param {SourceMC} method * @param {SourceMethodLike} method
* @param {ResolvedImport[]} imports * @param {ResolvedImport[]} imports
* @param {Map<string,CEIType>} typemap * @param {Map<string,CEIType>} typemap
*/ */
@@ -1201,7 +1189,7 @@ function catchType(tokens, mdecls, method, imports, typemap) {
* @param {SwitchStatement} s * @param {SwitchStatement} s
* @param {TokenList} tokens * @param {TokenList} tokens
* @param {MethodDeclarations} mdecls * @param {MethodDeclarations} mdecls
* @param {SourceMC} method * @param {SourceMethodLike} method
* @param {ResolvedImport[]} imports * @param {ResolvedImport[]} imports
* @param {Map<string,CEIType>} typemap * @param {Map<string,CEIType>} typemap
*/ */
@@ -1225,7 +1213,7 @@ function switchBlock(s, tokens, mdecls, method, imports, typemap) {
* @param {SwitchStatement} s * @param {SwitchStatement} s
* @param {TokenList} tokens * @param {TokenList} tokens
* @param {MethodDeclarations} mdecls * @param {MethodDeclarations} mdecls
* @param {SourceMC} method * @param {SourceMethodLike} method
* @param {ResolvedImport[]} imports * @param {ResolvedImport[]} imports
* @param {Map<string,CEIType>} typemap * @param {Map<string,CEIType>} typemap
*/ */
@@ -1250,7 +1238,7 @@ function caseBlock(s, tokens, mdecls, method, imports, typemap) {
* @param {(ResolvedIdent|boolean)[]} cases * @param {(ResolvedIdent|boolean)[]} cases
* @param {TokenList} tokens * @param {TokenList} tokens
* @param {MethodDeclarations} mdecls * @param {MethodDeclarations} mdecls
* @param {SourceMC} method * @param {SourceMethodLike} method
* @param {ResolvedImport[]} imports * @param {ResolvedImport[]} imports
* @param {Map<string,CEIType>} typemap * @param {Map<string,CEIType>} typemap
*/ */
@@ -1268,7 +1256,7 @@ function caseExpressionList(cases, tokens, mdecls, method, imports, typemap) {
/** /**
* @param {TokenList} tokens * @param {TokenList} tokens
* @param {MethodDeclarations} mdecls * @param {MethodDeclarations} mdecls
* @param {SourceMC} method * @param {SourceMethodLike} method
* @param {ResolvedImport[]} imports * @param {ResolvedImport[]} imports
* @param {Map<string,CEIType>} typemap * @param {Map<string,CEIType>} typemap
*/ */

View File

@@ -607,6 +607,10 @@ class FixedLengthArrayType extends SourceArrayType {
} }
} }
/**
* @typedef {SourceMethod|SourceConstructor|SourceInitialiser} SourceMethodLike
*/
exports.SourceType = SourceType; exports.SourceType = SourceType;
exports.SourceTypeIdent = SourceTypeIdent; exports.SourceTypeIdent = SourceTypeIdent;
exports.SourceField = SourceField; exports.SourceField = SourceField;

View File

@@ -3,12 +3,12 @@
* @typedef {import('../body-types').ResolvedIdent} ResolvedIdent * @typedef {import('../body-types').ResolvedIdent} ResolvedIdent
* @typedef {import('../body-types').ValidateInfo} ValidateInfo * @typedef {import('../body-types').ValidateInfo} ValidateInfo
*/ */
const { Statement } = require("./Statement"); const { KeywordStatement } = require("./KeywordStatement");
const ParseProblem = require('../parsetypes/parse-problem'); const ParseProblem = require('../parsetypes/parse-problem');
const { isTypeAssignable } = require('../expression-resolver'); const { isTypeAssignable } = require('../expression-resolver');
const { JavaType, PrimitiveType } = require('java-mti'); const { JavaType, PrimitiveType } = require('java-mti');
class AssertStatement extends Statement { class AssertStatement extends KeywordStatement {
/** @type {ResolvedIdent} */ /** @type {ResolvedIdent} */
expression = null; expression = null;
/** @type {ResolvedIdent} */ /** @type {ResolvedIdent} */

View File

@@ -4,10 +4,10 @@
* @typedef {import('../body-types').Label} Label * @typedef {import('../body-types').Label} Label
* @typedef {import('../body-types').ValidateInfo} ValidateInfo * @typedef {import('../body-types').ValidateInfo} ValidateInfo
* @typedef {import('../source-types').SourceType} SourceType * @typedef {import('../source-types').SourceType} SourceType
* @typedef {import('../source-types').SourceMethodLike} SourceMethodLike
*/ */
const { Statement } = require("./Statement"); const { Statement } = require("./Statement");
const ParseProblem = require('../parsetypes/parse-problem'); const ParseProblem = require('../parsetypes/parse-problem');
const { checkAssignment } = require('../expression-resolver');
class Block extends Statement { class Block extends Statement {
/** @type {Statement[]} */ /** @type {Statement[]} */
@@ -17,10 +17,11 @@ class Block extends Statement {
decls = null; decls = null;
/** /**
* @param {SourceMethodLike} owner
* @param {Token} open * @param {Token} open
*/ */
constructor(open) { constructor(owner, open) {
super(); super(owner);
this.open = open; this.open = open;
} }

View File

@@ -1,28 +1,21 @@
/** /**
* @typedef {import('../tokenizer').Token} Token * @typedef {import('../tokenizer').Token} Token
* @typedef {import('../body-types').ValidateInfo} ValidateInfo * @typedef {import('../body-types').ValidateInfo} ValidateInfo
* @typedef {import('../source-types').SourceMethodLike} SourceMethodLike
*/ */
const { Statement } = require("./Statement"); const { KeywordStatement } = require("./KeywordStatement");
const ParseProblem = require('../parsetypes/parse-problem'); const ParseProblem = require('../parsetypes/parse-problem');
class BreakStatement extends Statement { class BreakStatement extends KeywordStatement {
/** @type {Token} */ /** @type {Token} */
target = null; target = null;
/**
* @param {Token} token
*/
constructor(token) {
super();
this.break_token = token;
}
/** /**
* @param {ValidateInfo} vi * @param {ValidateInfo} vi
*/ */
validate(vi) { validate(vi) {
if (!vi.statementStack.find(s => /^(for|do|while|switch)$/.test(s))) { if (!vi.statementStack.find(s => /^(for|do|while|switch)$/.test(s))) {
vi.problems.push(ParseProblem.Error(this.break_token, `break can only be specified inside loop/switch statements`)); vi.problems.push(ParseProblem.Error(this.keyword, `break can only be specified inside loop/switch statements`));
} }
} }
} }

View File

@@ -1,28 +1,21 @@
/** /**
* @typedef {import('../tokenizer').Token} Token * @typedef {import('../tokenizer').Token} Token
* @typedef {import('../body-types').ValidateInfo} ValidateInfo * @typedef {import('../body-types').ValidateInfo} ValidateInfo
* @typedef {import('../source-types').SourceMethodLike} SourceMethodLike
*/ */
const { Statement } = require("./Statement"); const { KeywordStatement } = require("./KeywordStatement");
const ParseProblem = require('../parsetypes/parse-problem'); const ParseProblem = require('../parsetypes/parse-problem');
class ContinueStatement extends Statement { class ContinueStatement extends KeywordStatement {
/** @type {Token} */ /** @type {Token} */
target = null; target = null;
/**
* @param {Token} token
*/
constructor(token) {
super();
this.continue_token = token;
}
/** /**
* @param {ValidateInfo} vi * @param {ValidateInfo} vi
*/ */
validate(vi) { validate(vi) {
if (!vi.statementStack.find(s => /^(for|do|while)$/.test(s))) { if (!vi.statementStack.find(s => /^(for|do|while)$/.test(s))) {
vi.problems.push(ParseProblem.Error(this.continue_token, `continue can only be specified inside loop statements`)); vi.problems.push(ParseProblem.Error(this.keyword, `continue can only be specified inside loop statements`));
} }
} }
} }

View File

@@ -5,10 +5,10 @@
* @typedef {import('../expressiontypes/Expression').Expression} Expression * @typedef {import('../expressiontypes/Expression').Expression} Expression
* @typedef {import('../statementtypes/Block').Block} Block * @typedef {import('../statementtypes/Block').Block} Block
*/ */
const { Statement } = require("./Statement"); const { KeywordStatement } = require("./KeywordStatement");
const { checkBooleanBranchCondition } = require('../expression-resolver'); const { checkBooleanBranchCondition } = require('../expression-resolver');
class DoStatement extends Statement { class DoStatement extends KeywordStatement {
/** @type {ResolvedIdent} */ /** @type {ResolvedIdent} */
test = null; test = null;
/** @type {Block} */ /** @type {Block} */

View File

@@ -3,6 +3,7 @@
* @typedef {import('../body-types').ResolvedIdent} ResolvedIdent * @typedef {import('../body-types').ResolvedIdent} ResolvedIdent
* @typedef {import('../body-types').ValidateInfo} ValidateInfo * @typedef {import('../body-types').ValidateInfo} ValidateInfo
* @typedef {import('../expressiontypes/Expression').Expression} Expression * @typedef {import('../expressiontypes/Expression').Expression} Expression
* @typedef {import('../source-types').SourceMethodLike} SourceMethodLike
*/ */
const { Statement } = require("./Statement"); const { Statement } = require("./Statement");
const { BinaryOpExpression } = require('../expressiontypes/BinaryOpExpression'); const { BinaryOpExpression } = require('../expressiontypes/BinaryOpExpression');
@@ -13,10 +14,11 @@ const ParseProblem = require('../parsetypes/parse-problem');
class ExpressionStatement extends Statement { class ExpressionStatement extends Statement {
/** /**
* @param {SourceMethodLike} owner
* @param {ResolvedIdent} expression * @param {ResolvedIdent} expression
*/ */
constructor(expression) { constructor(owner, expression) {
super(); super(owner);
this.expression = expression; this.expression = expression;
} }

View File

@@ -1,13 +1,14 @@
/** /**
* @typedef {import('./Statement').Statement} Statement
* @typedef {import('../body-types').Local} Local * @typedef {import('../body-types').Local} Local
* @typedef {import('../body-types').ResolvedIdent} ResolvedIdent * @typedef {import('../body-types').ResolvedIdent} ResolvedIdent
* @typedef {import('../body-types').ValidateInfo} ValidateInfo * @typedef {import('../body-types').ValidateInfo} ValidateInfo
* @typedef {import('../tokenizer').Token} Token * @typedef {import('../tokenizer').Token} Token
*/ */
const { Statement } = require("./Statement"); const { KeywordStatement } = require("./KeywordStatement");
const { checkNonVarDeclStatement } = require('../statement-validater'); const { checkNonVarDeclStatement } = require('../statement-validater');
class ForStatement extends Statement { class ForStatement extends KeywordStatement {
/** @type {ResolvedIdent[] | Local[]} */ /** @type {ResolvedIdent[] | Local[]} */
init = null; init = null;
/** @type {ResolvedIdent} */ /** @type {ResolvedIdent} */

View File

@@ -1,12 +1,13 @@
/** /**
* @typedef {import('./Statement').Statement} Statement
* @typedef {import('../body-types').ResolvedIdent} ResolvedIdent * @typedef {import('../body-types').ResolvedIdent} ResolvedIdent
* @typedef {import('../body-types').ValidateInfo} ValidateInfo * @typedef {import('../body-types').ValidateInfo} ValidateInfo
*/ */
const { Statement } = require("./Statement"); const { KeywordStatement } = require("./KeywordStatement");
const { checkBooleanBranchCondition } = require('../expression-resolver'); const { checkBooleanBranchCondition } = require('../expression-resolver');
const { checkNonVarDeclStatement } = require('../statement-validater'); const { checkNonVarDeclStatement } = require('../statement-validater');
class IfStatement extends Statement { class IfStatement extends KeywordStatement {
/** @type {ResolvedIdent} */ /** @type {ResolvedIdent} */
test = null; test = null;
/** @type {Statement} */ /** @type {Statement} */

View File

@@ -1,15 +1,16 @@
/** /**
* @typedef {import('../tokenizer').Token} Token * @typedef {import('../tokenizer').Token} Token
* @typedef {import('../source-types').SourceMethodLike} SourceMethodLike
*/ */
const { Statement } = require("./Statement"); const { Statement } = require("./Statement");
class InvalidStatement extends Statement { class InvalidStatement extends Statement {
/** /**
* * @param {SourceMethodLike} owner
* @param {Token} token * @param {Token} token
*/ */
constructor(token) { constructor(owner, token) {
super(); super(owner);
this.token = token; this.token = token;
} }
} }

View File

@@ -0,0 +1,22 @@
/**
* @typedef {import('../tokenizer').Token} Token
* @typedef {import('../body-types').ValidateInfo} ValidateInfo
* @typedef {import('../source-types').SourceMethodLike} SourceMethodLike
*/
const { Statement } = require("./Statement");
/**
* A statement that begins with a keyword (if, do, while, etc)
*/
class KeywordStatement extends Statement {
/**
* @param {SourceMethodLike} owner
* @param {Token} keyword
*/
constructor(owner, keyword) {
super(owner);
this.keyword = keyword;
}
}
exports.KeywordStatement = KeywordStatement;

View File

@@ -4,6 +4,7 @@
* @typedef {import('../body-types').Label} Label * @typedef {import('../body-types').Label} Label
* @typedef {import('../body-types').ValidateInfo} ValidateInfo * @typedef {import('../body-types').ValidateInfo} ValidateInfo
* @typedef {import('../source-types').SourceType} SourceType * @typedef {import('../source-types').SourceType} SourceType
* @typedef {import('../source-types').SourceMethodLike} SourceMethodLike
*/ */
const { Statement } = require("./Statement"); const { Statement } = require("./Statement");
const ParseProblem = require('../parsetypes/parse-problem'); const ParseProblem = require('../parsetypes/parse-problem');
@@ -11,10 +12,11 @@ const { checkAssignment } = require('../expression-resolver');
class LocalDeclStatement extends Statement { class LocalDeclStatement extends Statement {
/** /**
* @param {SourceMethodLike} owner
* @param {Local[]} locals * @param {Local[]} locals
*/ */
constructor(locals) { constructor(owner, locals) {
super(); super(owner);
this.locals = locals; this.locals = locals;
} }

View File

@@ -2,27 +2,20 @@
* @typedef {import('../body-types').ResolvedIdent} ResolvedIdent * @typedef {import('../body-types').ResolvedIdent} ResolvedIdent
* @typedef {import('../body-types').ValidateInfo} ValidateInfo * @typedef {import('../body-types').ValidateInfo} ValidateInfo
* @typedef {import('../body-types').ResolvedValue} ResolvedValue * @typedef {import('../body-types').ResolvedValue} ResolvedValue
* @typedef {import('../source-types').SourceMethodLike} SourceMethodLike
* @typedef {import('../tokenizer').Token} Token * @typedef {import('../tokenizer').Token} Token
*/ */
const { JavaType, PrimitiveType } = require('java-mti'); const { JavaType, PrimitiveType } = require('java-mti');
const { Statement } = require("./Statement"); const { KeywordStatement } = require("./KeywordStatement");
const ParseProblem = require('../parsetypes/parse-problem'); const ParseProblem = require('../parsetypes/parse-problem');
const { isTypeAssignable } = require('../expression-resolver'); const { isTypeAssignable } = require('../expression-resolver');
const { NumberLiteral } = require('../expressiontypes/literals/Number'); const { NumberLiteral } = require('../expressiontypes/literals/Number');
const { LambdaType, MultiValueType } = require('../anys'); const { LambdaType, MultiValueType } = require('../anys');
class ReturnStatement extends Statement { class ReturnStatement extends KeywordStatement {
/** @type {ResolvedIdent} */ /** @type {ResolvedIdent} */
expression = null; expression = null;
/**
* @param {Token} return_token
*/
constructor(return_token) {
super();
this.return_token = return_token;
}
/** /**
* @param {ValidateInfo} vi * @param {ValidateInfo} vi
*/ */
@@ -30,7 +23,7 @@ class ReturnStatement extends Statement {
const method_return_type = vi.method.returnType; const method_return_type = vi.method.returnType;
if (!this.expression) { if (!this.expression) {
if (method_return_type !== PrimitiveType.map.V) { if (method_return_type !== PrimitiveType.map.V) {
vi.problems.push(ParseProblem.Error(this.return_token, `Method must return a value of type '${method_return_type.fullyDottedTypeName}'`)); vi.problems.push(ParseProblem.Error(this.keyword, `Method must return a value of type '${method_return_type.fullyDottedTypeName}'`));
} }
return; return;
} }

View File

@@ -1,7 +1,17 @@
/**
* @typedef {import('../source-types').SourceMethodLike} SourceMethodLike
*/
class Statement { class Statement {
validate(vi) {} /**
* @param {SourceMethodLike} owner
*/
constructor(owner) {
this.owner = owner;
}
validate(vi) {}
} }
exports.Statement = Statement; exports.Statement = Statement;

View File

@@ -1,15 +1,16 @@
/** /**
* @typedef {import('./Statement').Statement} Statement
* @typedef {import('../body-types').ResolvedIdent} ResolvedIdent * @typedef {import('../body-types').ResolvedIdent} ResolvedIdent
* @typedef {import('../body-types').ValidateInfo} ValidateInfo * @typedef {import('../body-types').ValidateInfo} ValidateInfo
* @typedef {import('../tokenizer').Token} Token * @typedef {import('../tokenizer').Token} Token
*/ */
const { JavaType, PrimitiveType } = require('java-mti'); const { JavaType, PrimitiveType } = require('java-mti');
const { Statement } = require("./Statement"); const { KeywordStatement } = require("./KeywordStatement");
const ParseProblem = require('../parsetypes/parse-problem'); const ParseProblem = require('../parsetypes/parse-problem');
const { isTypeAssignable } = require('../expression-resolver'); const { isTypeAssignable } = require('../expression-resolver');
const { NumberLiteral } = require('../expressiontypes/literals/Number'); const { NumberLiteral } = require('../expressiontypes/literals/Number');
class SwitchStatement extends Statement { class SwitchStatement extends KeywordStatement {
/** @type {ResolvedIdent} */ /** @type {ResolvedIdent} */
test = null; test = null;
/** @type {(ResolvedIdent|boolean)[]} */ /** @type {(ResolvedIdent|boolean)[]} */

View File

@@ -1,12 +1,13 @@
/** /**
* @typedef {import('./Statement').Statement} Statement
* @typedef {import('../body-types').ResolvedIdent} ResolvedIdent * @typedef {import('../body-types').ResolvedIdent} ResolvedIdent
* @typedef {import('../body-types').ValidateInfo} ValidateInfo * @typedef {import('../body-types').ValidateInfo} ValidateInfo
*/ */
const { CEIType } = require('java-mti'); const { CEIType } = require('java-mti');
const { Statement } = require("./Statement"); const { KeywordStatement } = require("./KeywordStatement");
const ParseProblem = require('../parsetypes/parse-problem'); const ParseProblem = require('../parsetypes/parse-problem');
class SynchronizedStatement extends Statement { class SynchronizedStatement extends KeywordStatement {
/** @type {ResolvedIdent} */ /** @type {ResolvedIdent} */
expression = null; expression = null;
/** @type {Statement} */ /** @type {Statement} */

View File

@@ -3,11 +3,11 @@
* @typedef {import('../body-types').ValidateInfo} ValidateInfo * @typedef {import('../body-types').ValidateInfo} ValidateInfo
*/ */
const { JavaType } = require('java-mti'); const { JavaType } = require('java-mti');
const { Statement } = require("./Statement"); const { KeywordStatement } = require("./KeywordStatement");
const { isTypeAssignable } = require('../expression-resolver'); const { isTypeAssignable } = require('../expression-resolver');
const ParseProblem = require('../parsetypes/parse-problem'); const ParseProblem = require('../parsetypes/parse-problem');
class ThrowStatement extends Statement { class ThrowStatement extends KeywordStatement {
/** @type {ResolvedIdent} */ /** @type {ResolvedIdent} */
expression = null; expression = null;

View File

@@ -3,11 +3,10 @@
* @typedef {import('./Block').Block} Block * @typedef {import('./Block').Block} Block
* @typedef {import('../body-types').Local} Local * @typedef {import('../body-types').Local} Local
*/ */
const { Statement } = require("./Statement"); const { KeywordStatement } = require("./KeywordStatement");
const { ResolvedIdent } = require('../body-types'); const { ResolvedIdent } = require('../body-types');
const ParseProblem = require('../parsetypes/parse-problem');
class TryStatement extends Statement { class TryStatement extends KeywordStatement {
/** @type {(ResolvedIdent|Local[])[]} */ /** @type {(ResolvedIdent|Local[])[]} */
resources = []; resources = [];
/** @type {Block} */ /** @type {Block} */

View File

@@ -1,11 +1,12 @@
/** /**
* @typedef {import('./Statement').Statement} Statement
* @typedef {import('../body-types').ResolvedIdent} ResolvedIdent * @typedef {import('../body-types').ResolvedIdent} ResolvedIdent
* @typedef {import('../body-types').ValidateInfo} ValidateInfo * @typedef {import('../body-types').ValidateInfo} ValidateInfo
*/ */
const { Statement } = require("./Statement"); const { KeywordStatement } = require("./KeywordStatement");
const { checkBooleanBranchCondition } = require('../expression-resolver'); const { checkBooleanBranchCondition } = require('../expression-resolver');
class WhileStatement extends Statement { class WhileStatement extends KeywordStatement {
/** @type {ResolvedIdent} */ /** @type {ResolvedIdent} */
test = null; test = null;
/** @type {Statement} */ /** @type {Statement} */