1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2024-09-08 17:54:40 +00:00

Implemented ternary operator. Closes #77

This commit is contained in:
jespergravgaard 2019-04-07 17:59:44 +02:00
parent e1cf957b2f
commit 67b97130b7
26 changed files with 1918 additions and 843 deletions

View File

@ -103,6 +103,11 @@ public class CompileLog {
this.verboseStatementSequence = verboseStatementSequence;
}
public CompileLog verboseStatementSequence() {
setVerboseStatementSequence(true);
return this;
}
public void setVerboseComments(boolean verboseComments) {
this.verboseComments = verboseComments;
}

View File

@ -656,7 +656,7 @@ public abstract class ProgramValue {
private final StatementPhiBlock.PhiVariable phiVariable;
private final int i;
PhiValue(StatementPhiBlock.PhiVariable phiVariable, int i) {
public PhiValue(StatementPhiBlock.PhiVariable phiVariable, int i) {
this.phiVariable = phiVariable;
this.i = i;
}

View File

@ -6,10 +6,7 @@ import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.operators.Operator;
import dk.camelot64.kickc.model.operators.OperatorBinary;
import dk.camelot64.kickc.model.operators.OperatorUnary;
import dk.camelot64.kickc.model.statements.StatementAssignment;
import dk.camelot64.kickc.model.statements.StatementCall;
import dk.camelot64.kickc.model.statements.StatementCallPointer;
import dk.camelot64.kickc.model.statements.StatementLValue;
import dk.camelot64.kickc.model.statements.*;
import dk.camelot64.kickc.model.symbols.*;
import dk.camelot64.kickc.model.values.*;
@ -343,6 +340,32 @@ public class SymbolTypeInference {
}
}
public static void inferPhiVariable(Program program, StatementPhiBlock.PhiVariable phiVariable, boolean reinfer) {
ProgramScope programScope = program.getScope();
Variable symbol = programScope.getVariable(phiVariable.getVariable());
if(SymbolType.VAR.equals(symbol.getType()) || (reinfer && symbol.isInferredType())) {
SymbolType type = null;
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
RValue rValue = phiRValue.getrValue();
SymbolType valueType = inferType(programScope, rValue);
if(type == null) {
type = valueType;
} else {
SymbolType newType = intersectTypes(type, valueType);
if(newType == null) {
throw new CompileError("Types not compatible " + type + " and " + valueType);
}
type = newType;
}
}
if(!SymbolType.VAR.equals(symbol.getType()) && !type.equals(symbol.getType())) {
program.getLog().append("Inferred type updated to " + type + " for " + symbol.toString(program));
}
symbol.setTypeInferred(type);
}
}
public static void inferAssignmentLValue(Program program, StatementAssignment assignment, boolean reinfer) {
ProgramScope programScope = program.getScope();
LValue lValue = assignment.getlValue();
@ -381,9 +404,9 @@ public class SymbolTypeInference {
}
}
private static void setInferedType(Program program, StatementLValue statementLValue, Variable symbol, SymbolType type) {
private static void setInferedType(Program program, Statement statement, Variable symbol, SymbolType type) {
if(!SymbolType.VAR.equals(symbol.getType()) && !type.equals(symbol.getType())) {
program.getLog().append("Inferred type updated to " + type + " in " + statementLValue.toString(program, false));
program.getLog().append("Inferred type updated to " + type + " in " + statement.toString(program, false));
}
symbol.setTypeInferred(type);
}

View File

@ -107,6 +107,7 @@ expr
| expr ( '|' ) expr #exprBinary
| expr ( '&&' ) expr #exprBinary
| expr ( '||' ) expr #exprBinary
| expr '?' expr ':' expr #exprTernary
| <assoc=right> expr '=' expr #exprAssignment
| <assoc=right> expr ('+=' | '-=' | '*=' | '/=' | '%=' | '<<=' | '>>=' | '&=' | '|=' | '^=' ) expr #exprAssignmentCompound
| '{' expr (',' expr )* '}' #initList

View File

@ -69,26 +69,27 @@ T__67=68
T__68=69
T__69=70
T__70=71
MNEMONIC=72
KICKASM=73
SIMPLETYPE=74
STRING=75
CHAR=76
BOOLEAN=77
NUMBER=78
NUMFLOAT=79
BINFLOAT=80
DECFLOAT=81
HEXFLOAT=82
NUMINT=83
BININTEGER=84
DECINTEGER=85
HEXINTEGER=86
NAME=87
ASMREL=88
WS=89
COMMENT_LINE=90
COMMENT_BLOCK=91
T__71=72
MNEMONIC=73
KICKASM=74
SIMPLETYPE=75
STRING=76
CHAR=77
BOOLEAN=78
NUMBER=79
NUMFLOAT=80
BINFLOAT=81
DECFLOAT=82
HEXFLOAT=83
NUMINT=84
BININTEGER=85
DECINTEGER=86
HEXINTEGER=87
NAME=88
ASMREL=89
WS=90
COMMENT_LINE=91
COMMENT_BLOCK=92
'import'=1
'='=2
';'=3
@ -140,23 +141,24 @@ COMMENT_BLOCK=91
'|'=49
'&&'=50
'||'=51
'+='=52
'-='=53
'*='=54
'/='=55
'%='=56
'<<='=57
'>>='=58
'&='=59
'|='=60
'^='=61
'kickasm'=62
'resource'=63
'uses'=64
'clobbers'=65
'bytes'=66
'cycles'=67
'pc'=68
'.byte'=69
'#'=70
'.'=71
'?'=52
'+='=53
'-='=54
'*='=55
'/='=56
'%='=57
'<<='=58
'>>='=59
'&='=60
'|='=61
'^='=62
'kickasm'=63
'resource'=64
'uses'=65
'clobbers'=66
'bytes'=67
'cycles'=68
'pc'=69
'.byte'=70
'#'=71
'.'=72

View File

@ -659,6 +659,18 @@ public class KickCBaseListener implements KickCListener {
* <p>The default implementation does nothing.</p>
*/
@Override public void exitExprId(KickCParser.ExprIdContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void enterExprTernary(KickCParser.ExprTernaryContext ctx) { }
/**
* {@inheritDoc}
*
* <p>The default implementation does nothing.</p>
*/
@Override public void exitExprTernary(KickCParser.ExprTernaryContext ctx) { }
/**
* {@inheritDoc}
*

View File

@ -389,6 +389,13 @@ public class KickCBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitExprId(KickCParser.ExprIdContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitExprTernary(KickCParser.ExprTernaryContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*

View File

@ -26,10 +26,11 @@ public class KickCLexer extends Lexer {
T__45=46, T__46=47, T__47=48, T__48=49, T__49=50, T__50=51, T__51=52,
T__52=53, T__53=54, T__54=55, T__55=56, T__56=57, T__57=58, T__58=59,
T__59=60, T__60=61, T__61=62, T__62=63, T__63=64, T__64=65, T__65=66,
T__66=67, T__67=68, T__68=69, T__69=70, T__70=71, MNEMONIC=72, KICKASM=73,
SIMPLETYPE=74, STRING=75, CHAR=76, BOOLEAN=77, NUMBER=78, NUMFLOAT=79,
BINFLOAT=80, DECFLOAT=81, HEXFLOAT=82, NUMINT=83, BININTEGER=84, DECINTEGER=85,
HEXINTEGER=86, NAME=87, ASMREL=88, WS=89, COMMENT_LINE=90, COMMENT_BLOCK=91;
T__66=67, T__67=68, T__68=69, T__69=70, T__70=71, T__71=72, MNEMONIC=73,
KICKASM=74, SIMPLETYPE=75, STRING=76, CHAR=77, BOOLEAN=78, NUMBER=79,
NUMFLOAT=80, BINFLOAT=81, DECFLOAT=82, HEXFLOAT=83, NUMINT=84, BININTEGER=85,
DECINTEGER=86, HEXINTEGER=87, NAME=88, ASMREL=89, WS=90, COMMENT_LINE=91,
COMMENT_BLOCK=92;
public static String[] channelNames = {
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
};
@ -47,11 +48,11 @@ public class KickCLexer extends Lexer {
"T__41", "T__42", "T__43", "T__44", "T__45", "T__46", "T__47", "T__48",
"T__49", "T__50", "T__51", "T__52", "T__53", "T__54", "T__55", "T__56",
"T__57", "T__58", "T__59", "T__60", "T__61", "T__62", "T__63", "T__64",
"T__65", "T__66", "T__67", "T__68", "T__69", "T__70", "MNEMONIC", "KICKASM",
"SIMPLETYPE", "STRING", "CHAR", "BOOLEAN", "NUMBER", "NUMFLOAT", "BINFLOAT",
"DECFLOAT", "HEXFLOAT", "NUMINT", "BININTEGER", "DECINTEGER", "HEXINTEGER",
"BINDIGIT", "DECDIGIT", "HEXDIGIT", "NAME", "NAME_START", "NAME_CHAR",
"ASMREL", "WS", "COMMENT_LINE", "COMMENT_BLOCK"
"T__65", "T__66", "T__67", "T__68", "T__69", "T__70", "T__71", "MNEMONIC",
"KICKASM", "SIMPLETYPE", "STRING", "CHAR", "BOOLEAN", "NUMBER", "NUMFLOAT",
"BINFLOAT", "DECFLOAT", "HEXFLOAT", "NUMINT", "BININTEGER", "DECINTEGER",
"HEXINTEGER", "BINDIGIT", "DECDIGIT", "HEXDIGIT", "NAME", "NAME_START",
"NAME_CHAR", "ASMREL", "WS", "COMMENT_LINE", "COMMENT_BLOCK"
};
private static final String[] _LITERAL_NAMES = {
@ -60,10 +61,10 @@ public class KickCLexer extends Lexer {
"'if'", "'else'", "'while'", "'do'", "'for'", "'return'", "'break'", "'continue'",
"'asm'", "':'", "'..'", "'signed'", "'*'", "'['", "']'", "'--'", "'++'",
"'+'", "'-'", "'!'", "'&'", "'~'", "'>>'", "'<<'", "'/'", "'%'", "'<'",
"'>'", "'=='", "'!='", "'<='", "'>='", "'^'", "'|'", "'&&'", "'||'", "'+='",
"'-='", "'*='", "'/='", "'%='", "'<<='", "'>>='", "'&='", "'|='", "'^='",
"'kickasm'", "'resource'", "'uses'", "'clobbers'", "'bytes'", "'cycles'",
"'pc'", "'.byte'", "'#'", "'.'"
"'>'", "'=='", "'!='", "'<='", "'>='", "'^'", "'|'", "'&&'", "'||'", "'?'",
"'+='", "'-='", "'*='", "'/='", "'%='", "'<<='", "'>>='", "'&='", "'|='",
"'^='", "'kickasm'", "'resource'", "'uses'", "'clobbers'", "'bytes'",
"'cycles'", "'pc'", "'.byte'", "'#'", "'.'"
};
private static final String[] _SYMBOLIC_NAMES = {
null, null, null, null, null, null, null, null, null, null, null, null,
@ -72,8 +73,8 @@ public class KickCLexer extends Lexer {
null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null,
null, null, null, null, null, null, null, null, null, null, null, null,
"MNEMONIC", "KICKASM", "SIMPLETYPE", "STRING", "CHAR", "BOOLEAN", "NUMBER",
"NUMFLOAT", "BINFLOAT", "DECFLOAT", "HEXFLOAT", "NUMINT", "BININTEGER",
null, "MNEMONIC", "KICKASM", "SIMPLETYPE", "STRING", "CHAR", "BOOLEAN",
"NUMBER", "NUMFLOAT", "BINFLOAT", "DECFLOAT", "HEXFLOAT", "NUMINT", "BININTEGER",
"DECINTEGER", "HEXINTEGER", "NAME", "ASMREL", "WS", "COMMENT_LINE", "COMMENT_BLOCK"
};
public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
@ -134,7 +135,7 @@ public class KickCLexer extends Lexer {
public ATN getATN() { return _ATN; }
public static final String _serializedATN =
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2]\u039a\b\1\4\2\t"+
"\3\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786\u5964\2^\u039e\b\1\4\2\t"+
"\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+
"\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+
"\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+
@ -145,326 +146,328 @@ public class KickCLexer extends Lexer {
"\4>\t>\4?\t?\4@\t@\4A\tA\4B\tB\4C\tC\4D\tD\4E\tE\4F\tF\4G\tG\4H\tH\4I"+
"\tI\4J\tJ\4K\tK\4L\tL\4M\tM\4N\tN\4O\tO\4P\tP\4Q\tQ\4R\tR\4S\tS\4T\tT"+
"\4U\tU\4V\tV\4W\tW\4X\tX\4Y\tY\4Z\tZ\4[\t[\4\\\t\\\4]\t]\4^\t^\4_\t_\4"+
"`\t`\4a\ta\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\3\3\3\3\4\3\4\3\5\3\5\3\6\3\6"+
"\3\7\3\7\3\b\3\b\3\t\3\t\3\n\3\n\3\n\3\n\3\n\3\n\3\13\3\13\3\13\3\13\3"+
"\13\3\13\3\13\3\f\3\f\3\f\3\f\3\f\3\f\3\r\3\r\3\r\3\r\3\r\3\r\3\r\3\r"+
"\3\r\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\17\3\17\3\17\3\17\3\17\3\17"+
"\3\17\3\17\3\17\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\21"+
"\3\21\3\21\3\22\3\22\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\23\3\24"+
"\3\24\3\24\3\25\3\25\3\25\3\25\3\26\3\26\3\26\3\26\3\26\3\26\3\26\3\27"+
"\3\27\3\27\3\27\3\27\3\27\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30"+
"\3\31\3\31\3\31\3\31\3\32\3\32\3\33\3\33\3\33\3\34\3\34\3\34\3\34\3\34"+
"\3\34\3\34\3\35\3\35\3\36\3\36\3\37\3\37\3 \3 \3 \3!\3!\3!\3\"\3\"\3#"+
"\3#\3$\3$\3%\3%\3&\3&\3\'\3\'\3\'\3(\3(\3(\3)\3)\3*\3*\3+\3+\3,\3,\3-"+
"\3-\3-\3.\3.\3.\3/\3/\3/\3\60\3\60\3\60\3\61\3\61\3\62\3\62\3\63\3\63"+
"\3\63\3\64\3\64\3\64\3\65\3\65\3\65\3\66\3\66\3\66\3\67\3\67\3\67\38\3"+
"8\38\39\39\39\3:\3:\3:\3:\3;\3;\3;\3;\3<\3<\3<\3=\3=\3=\3>\3>\3>\3?\3"+
"?\3?\3?\3?\3?\3?\3?\3@\3@\3@\3@\3@\3@\3@\3@\3@\3A\3A\3A\3A\3A\3B\3B\3"+
"B\3B\3B\3B\3B\3B\3B\3C\3C\3C\3C\3C\3C\3D\3D\3D\3D\3D\3D\3D\3E\3E\3E\3"+
"F\3F\3F\3F\3F\3F\3G\3G\3H\3H\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3"+
"I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3"+
"I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3"+
"I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3"+
"I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3"+
"I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3"+
"I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3"+
"I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3"+
"I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3"+
"I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3I\3"+
"I\3I\5I\u02bb\nI\3J\3J\3J\3J\7J\u02c1\nJ\fJ\16J\u02c4\13J\3J\3J\3J\3K"+
"\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\3K\5K\u02de"+
"\nK\3L\3L\3L\3L\7L\u02e4\nL\fL\16L\u02e7\13L\3L\3L\3M\3M\3M\3M\5M\u02ef"+
"\nM\3M\3M\3N\3N\3N\3N\3N\3N\3N\3N\3N\5N\u02fc\nN\3O\3O\5O\u0300\nO\3P"+
"\3P\3P\5P\u0305\nP\3Q\3Q\3Q\3Q\3Q\5Q\u030c\nQ\3Q\7Q\u030f\nQ\fQ\16Q\u0312"+
"\13Q\3Q\3Q\6Q\u0316\nQ\rQ\16Q\u0317\3R\7R\u031b\nR\fR\16R\u031e\13R\3"+
"R\3R\6R\u0322\nR\rR\16R\u0323\3S\3S\3S\3S\3S\5S\u032b\nS\3S\7S\u032e\n"+
"S\fS\16S\u0331\13S\3S\3S\6S\u0335\nS\rS\16S\u0336\3T\3T\3T\5T\u033c\n"+
"T\3U\3U\3U\6U\u0341\nU\rU\16U\u0342\3U\3U\6U\u0347\nU\rU\16U\u0348\5U"+
"\u034b\nU\3V\6V\u034e\nV\rV\16V\u034f\3W\3W\3W\3W\3W\5W\u0357\nW\3W\6"+
"W\u035a\nW\rW\16W\u035b\3X\3X\3Y\3Y\3Z\3Z\3[\3[\7[\u0366\n[\f[\16[\u0369"+
"\13[\3\\\3\\\3]\3]\3^\3^\7^\u0371\n^\f^\16^\u0374\13^\3^\6^\u0377\n^\r"+
"^\16^\u0378\3_\6_\u037c\n_\r_\16_\u037d\3_\3_\3`\3`\3`\3`\7`\u0386\n`"+
"\f`\16`\u0389\13`\3`\3`\3a\3a\3a\3a\7a\u0391\na\fa\16a\u0394\13a\3a\3"+
"a\3a\3a\3a\4\u02c2\u0392\2b\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13\25"+
"\f\27\r\31\16\33\17\35\20\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61\32"+
"\63\33\65\34\67\359\36;\37= ?!A\"C#E$G%I&K\'M(O)Q*S+U,W-Y.[/]\60_\61a"+
"\62c\63e\64g\65i\66k\67m8o9q:s;u<w=y>{?}@\177A\u0081B\u0083C\u0085D\u0087"+
"`\t`\4a\ta\4b\tb\3\2\3\2\3\2\3\2\3\2\3\2\3\2\3\3\3\3\3\4\3\4\3\5\3\5\3"+
"\6\3\6\3\7\3\7\3\b\3\b\3\t\3\t\3\n\3\n\3\n\3\n\3\n\3\n\3\13\3\13\3\13"+
"\3\13\3\13\3\13\3\13\3\f\3\f\3\f\3\f\3\f\3\f\3\r\3\r\3\r\3\r\3\r\3\r\3"+
"\r\3\r\3\r\3\16\3\16\3\16\3\16\3\16\3\16\3\16\3\17\3\17\3\17\3\17\3\17"+
"\3\17\3\17\3\17\3\17\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20\3\20"+
"\3\21\3\21\3\21\3\22\3\22\3\22\3\22\3\22\3\23\3\23\3\23\3\23\3\23\3\23"+
"\3\24\3\24\3\24\3\25\3\25\3\25\3\25\3\26\3\26\3\26\3\26\3\26\3\26\3\26"+
"\3\27\3\27\3\27\3\27\3\27\3\27\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30"+
"\3\30\3\31\3\31\3\31\3\31\3\32\3\32\3\33\3\33\3\33\3\34\3\34\3\34\3\34"+
"\3\34\3\34\3\34\3\35\3\35\3\36\3\36\3\37\3\37\3 \3 \3 \3!\3!\3!\3\"\3"+
"\"\3#\3#\3$\3$\3%\3%\3&\3&\3\'\3\'\3\'\3(\3(\3(\3)\3)\3*\3*\3+\3+\3,\3"+
",\3-\3-\3-\3.\3.\3.\3/\3/\3/\3\60\3\60\3\60\3\61\3\61\3\62\3\62\3\63\3"+
"\63\3\63\3\64\3\64\3\64\3\65\3\65\3\66\3\66\3\66\3\67\3\67\3\67\38\38"+
"\38\39\39\39\3:\3:\3:\3;\3;\3;\3;\3<\3<\3<\3<\3=\3=\3=\3>\3>\3>\3?\3?"+
"\3?\3@\3@\3@\3@\3@\3@\3@\3@\3A\3A\3A\3A\3A\3A\3A\3A\3A\3B\3B\3B\3B\3B"+
"\3C\3C\3C\3C\3C\3C\3C\3C\3C\3D\3D\3D\3D\3D\3D\3E\3E\3E\3E\3E\3E\3E\3F"+
"\3F\3F\3G\3G\3G\3G\3G\3G\3H\3H\3I\3I\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J"+
"\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J"+
"\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J"+
"\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J"+
"\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J"+
"\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J"+
"\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J"+
"\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J"+
"\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J"+
"\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J\3J"+
"\3J\3J\3J\3J\5J\u02bf\nJ\3K\3K\3K\3K\7K\u02c5\nK\fK\16K\u02c8\13K\3K\3"+
"K\3K\3L\3L\3L\3L\3L\3L\3L\3L\3L\3L\3L\3L\3L\3L\3L\3L\3L\3L\3L\3L\3L\5"+
"L\u02e2\nL\3M\3M\3M\3M\7M\u02e8\nM\fM\16M\u02eb\13M\3M\3M\3N\3N\3N\3N"+
"\5N\u02f3\nN\3N\3N\3O\3O\3O\3O\3O\3O\3O\3O\3O\5O\u0300\nO\3P\3P\5P\u0304"+
"\nP\3Q\3Q\3Q\5Q\u0309\nQ\3R\3R\3R\3R\3R\5R\u0310\nR\3R\7R\u0313\nR\fR"+
"\16R\u0316\13R\3R\3R\6R\u031a\nR\rR\16R\u031b\3S\7S\u031f\nS\fS\16S\u0322"+
"\13S\3S\3S\6S\u0326\nS\rS\16S\u0327\3T\3T\3T\3T\3T\5T\u032f\nT\3T\7T\u0332"+
"\nT\fT\16T\u0335\13T\3T\3T\6T\u0339\nT\rT\16T\u033a\3U\3U\3U\5U\u0340"+
"\nU\3V\3V\3V\6V\u0345\nV\rV\16V\u0346\3V\3V\6V\u034b\nV\rV\16V\u034c\5"+
"V\u034f\nV\3W\6W\u0352\nW\rW\16W\u0353\3X\3X\3X\3X\3X\5X\u035b\nX\3X\6"+
"X\u035e\nX\rX\16X\u035f\3Y\3Y\3Z\3Z\3[\3[\3\\\3\\\7\\\u036a\n\\\f\\\16"+
"\\\u036d\13\\\3]\3]\3^\3^\3_\3_\7_\u0375\n_\f_\16_\u0378\13_\3_\6_\u037b"+
"\n_\r_\16_\u037c\3`\6`\u0380\n`\r`\16`\u0381\3`\3`\3a\3a\3a\3a\7a\u038a"+
"\na\fa\16a\u038d\13a\3a\3a\3b\3b\3b\3b\7b\u0395\nb\fb\16b\u0398\13b\3"+
"b\3b\3b\3b\3b\4\u02c6\u0396\2c\3\3\5\4\7\5\t\6\13\7\r\b\17\t\21\n\23\13"+
"\25\f\27\r\31\16\33\17\35\20\37\21!\22#\23%\24\'\25)\26+\27-\30/\31\61"+
"\32\63\33\65\34\67\359\36;\37= ?!A\"C#E$G%I&K\'M(O)Q*S+U,W-Y.[/]\60_\61"+
"a\62c\63e\64g\65i\66k\67m8o9q:s;u<w=y>{?}@\177A\u0081B\u0083C\u0085D\u0087"+
"E\u0089F\u008bG\u008dH\u008fI\u0091J\u0093K\u0095L\u0097M\u0099N\u009b"+
"O\u009dP\u009fQ\u00a1R\u00a3S\u00a5T\u00a7U\u00a9V\u00abW\u00adX\u00af"+
"\2\u00b1\2\u00b3\2\u00b5Y\u00b7\2\u00b9\2\u00bbZ\u00bd[\u00bf\\\u00c1"+
"]\3\2\r\3\2$$\3\2))\4\2DDdd\3\2\62\63\3\2\62;\5\2\62;CHch\5\2C\\aac|\6"+
"\2\62;C\\aac|\4\2--//\6\2\13\f\17\17\"\"\u00a2\u00a2\4\2\f\f\17\17\2\u0402"+
"\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2"+
"\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2"+
"\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2"+
"\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2"+
"\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3"+
"\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2"+
"\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2"+
"U\3\2\2\2\2W\3\2\2\2\2Y\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2\2_\3\2\2\2\2a\3"+
"\2\2\2\2c\3\2\2\2\2e\3\2\2\2\2g\3\2\2\2\2i\3\2\2\2\2k\3\2\2\2\2m\3\2\2"+
"\2\2o\3\2\2\2\2q\3\2\2\2\2s\3\2\2\2\2u\3\2\2\2\2w\3\2\2\2\2y\3\2\2\2\2"+
"{\3\2\2\2\2}\3\2\2\2\2\177\3\2\2\2\2\u0081\3\2\2\2\2\u0083\3\2\2\2\2\u0085"+
"\3\2\2\2\2\u0087\3\2\2\2\2\u0089\3\2\2\2\2\u008b\3\2\2\2\2\u008d\3\2\2"+
"\2\2\u008f\3\2\2\2\2\u0091\3\2\2\2\2\u0093\3\2\2\2\2\u0095\3\2\2\2\2\u0097"+
"\3\2\2\2\2\u0099\3\2\2\2\2\u009b\3\2\2\2\2\u009d\3\2\2\2\2\u009f\3\2\2"+
"\2\2\u00a1\3\2\2\2\2\u00a3\3\2\2\2\2\u00a5\3\2\2\2\2\u00a7\3\2\2\2\2\u00a9"+
"\3\2\2\2\2\u00ab\3\2\2\2\2\u00ad\3\2\2\2\2\u00b5\3\2\2\2\2\u00bb\3\2\2"+
"\2\2\u00bd\3\2\2\2\2\u00bf\3\2\2\2\2\u00c1\3\2\2\2\3\u00c3\3\2\2\2\5\u00ca"+
"\3\2\2\2\7\u00cc\3\2\2\2\t\u00ce\3\2\2\2\13\u00d0\3\2\2\2\r\u00d2\3\2"+
"\2\2\17\u00d4\3\2\2\2\21\u00d6\3\2\2\2\23\u00d8\3\2\2\2\25\u00de\3\2\2"+
"\2\27\u00e5\3\2\2\2\31\u00eb\3\2\2\2\33\u00f4\3\2\2\2\35\u00fb\3\2\2\2"+
"\37\u0104\3\2\2\2!\u010e\3\2\2\2#\u0111\3\2\2\2%\u0116\3\2\2\2\'\u011c"+
"\3\2\2\2)\u011f\3\2\2\2+\u0123\3\2\2\2-\u012a\3\2\2\2/\u0130\3\2\2\2\61"+
"\u0139\3\2\2\2\63\u013d\3\2\2\2\65\u013f\3\2\2\2\67\u0142\3\2\2\29\u0149"+
"\3\2\2\2;\u014b\3\2\2\2=\u014d\3\2\2\2?\u014f\3\2\2\2A\u0152\3\2\2\2C"+
"\u0155\3\2\2\2E\u0157\3\2\2\2G\u0159\3\2\2\2I\u015b\3\2\2\2K\u015d\3\2"+
"\2\2M\u015f\3\2\2\2O\u0162\3\2\2\2Q\u0165\3\2\2\2S\u0167\3\2\2\2U\u0169"+
"\3\2\2\2W\u016b\3\2\2\2Y\u016d\3\2\2\2[\u0170\3\2\2\2]\u0173\3\2\2\2_"+
"\u0176\3\2\2\2a\u0179\3\2\2\2c\u017b\3\2\2\2e\u017d\3\2\2\2g\u0180\3\2"+
"\2\2i\u0183\3\2\2\2k\u0186\3\2\2\2m\u0189\3\2\2\2o\u018c\3\2\2\2q\u018f"+
"\3\2\2\2s\u0192\3\2\2\2u\u0196\3\2\2\2w\u019a\3\2\2\2y\u019d\3\2\2\2{"+
"\u01a0\3\2\2\2}\u01a3\3\2\2\2\177\u01ab\3\2\2\2\u0081\u01b4\3\2\2\2\u0083"+
"\u01b9\3\2\2\2\u0085\u01c2\3\2\2\2\u0087\u01c8\3\2\2\2\u0089\u01cf\3\2"+
"\2\2\u008b\u01d2\3\2\2\2\u008d\u01d8\3\2\2\2\u008f\u01da\3\2\2\2\u0091"+
"\u02ba\3\2\2\2\u0093\u02bc\3\2\2\2\u0095\u02dd\3\2\2\2\u0097\u02df\3\2"+
"\2\2\u0099\u02ea\3\2\2\2\u009b\u02fb\3\2\2\2\u009d\u02ff\3\2\2\2\u009f"+
"\u0304\3\2\2\2\u00a1\u030b\3\2\2\2\u00a3\u031c\3\2\2\2\u00a5\u032a\3\2"+
"\2\2\u00a7\u033b\3\2\2\2\u00a9\u034a\3\2\2\2\u00ab\u034d\3\2\2\2\u00ad"+
"\u0356\3\2\2\2\u00af\u035d\3\2\2\2\u00b1\u035f\3\2\2\2\u00b3\u0361\3\2"+
"\2\2\u00b5\u0363\3\2\2\2\u00b7\u036a\3\2\2\2\u00b9\u036c\3\2\2\2\u00bb"+
"\u036e\3\2\2\2\u00bd\u037b\3\2\2\2\u00bf\u0381\3\2\2\2\u00c1\u038c\3\2"+
"\2\2\u00c3\u00c4\7k\2\2\u00c4\u00c5\7o\2\2\u00c5\u00c6\7r\2\2\u00c6\u00c7"+
"\7q\2\2\u00c7\u00c8\7t\2\2\u00c8\u00c9\7v\2\2\u00c9\4\3\2\2\2\u00ca\u00cb"+
"\7?\2\2\u00cb\6\3\2\2\2\u00cc\u00cd\7=\2\2\u00cd\b\3\2\2\2\u00ce\u00cf"+
"\7*\2\2\u00cf\n\3\2\2\2\u00d0\u00d1\7+\2\2\u00d1\f\3\2\2\2\u00d2\u00d3"+
"\7}\2\2\u00d3\16\3\2\2\2\u00d4\u00d5\7\177\2\2\u00d5\20\3\2\2\2\u00d6"+
"\u00d7\7.\2\2\u00d7\22\3\2\2\2\u00d8\u00d9\7e\2\2\u00d9\u00da\7q\2\2\u00da"+
"\u00db\7p\2\2\u00db\u00dc\7u\2\2\u00dc\u00dd\7v\2\2\u00dd\24\3\2\2\2\u00de"+
"\u00df\7g\2\2\u00df\u00e0\7z\2\2\u00e0\u00e1\7v\2\2\u00e1\u00e2\7g\2\2"+
"\u00e2\u00e3\7t\2\2\u00e3\u00e4\7p\2\2\u00e4\26\3\2\2\2\u00e5\u00e6\7"+
"c\2\2\u00e6\u00e7\7n\2\2\u00e7\u00e8\7k\2\2\u00e8\u00e9\7i\2\2\u00e9\u00ea"+
"\7p\2\2\u00ea\30\3\2\2\2\u00eb\u00ec\7t\2\2\u00ec\u00ed\7g\2\2\u00ed\u00ee"+
"\7i\2\2\u00ee\u00ef\7k\2\2\u00ef\u00f0\7u\2\2\u00f0\u00f1\7v\2\2\u00f1"+
"\u00f2\7g\2\2\u00f2\u00f3\7t\2\2\u00f3\32\3\2\2\2\u00f4\u00f5\7k\2\2\u00f5"+
"\u00f6\7p\2\2\u00f6\u00f7\7n\2\2\u00f7\u00f8\7k\2\2\u00f8\u00f9\7p\2\2"+
"\u00f9\u00fa\7g\2\2\u00fa\34\3\2\2\2\u00fb\u00fc\7x\2\2\u00fc\u00fd\7"+
"q\2\2\u00fd\u00fe\7n\2\2\u00fe\u00ff\7c\2\2\u00ff\u0100\7v\2\2\u0100\u0101"+
"\7k\2\2\u0101\u0102\7n\2\2\u0102\u0103\7g\2\2\u0103\36\3\2\2\2\u0104\u0105"+
"\7k\2\2\u0105\u0106\7p\2\2\u0106\u0107\7v\2\2\u0107\u0108\7g\2\2\u0108"+
"\u0109\7t\2\2\u0109\u010a\7t\2\2\u010a\u010b\7w\2\2\u010b\u010c\7r\2\2"+
"\u010c\u010d\7v\2\2\u010d \3\2\2\2\u010e\u010f\7k\2\2\u010f\u0110\7h\2"+
"\2\u0110\"\3\2\2\2\u0111\u0112\7g\2\2\u0112\u0113\7n\2\2\u0113\u0114\7"+
"u\2\2\u0114\u0115\7g\2\2\u0115$\3\2\2\2\u0116\u0117\7y\2\2\u0117\u0118"+
"\7j\2\2\u0118\u0119\7k\2\2\u0119\u011a\7n\2\2\u011a\u011b\7g\2\2\u011b"+
"&\3\2\2\2\u011c\u011d\7f\2\2\u011d\u011e\7q\2\2\u011e(\3\2\2\2\u011f\u0120"+
"\7h\2\2\u0120\u0121\7q\2\2\u0121\u0122\7t\2\2\u0122*\3\2\2\2\u0123\u0124"+
"\7t\2\2\u0124\u0125\7g\2\2\u0125\u0126\7v\2\2\u0126\u0127\7w\2\2\u0127"+
"\u0128\7t\2\2\u0128\u0129\7p\2\2\u0129,\3\2\2\2\u012a\u012b\7d\2\2\u012b"+
"\u012c\7t\2\2\u012c\u012d\7g\2\2\u012d\u012e\7c\2\2\u012e\u012f\7m\2\2"+
"\u012f.\3\2\2\2\u0130\u0131\7e\2\2\u0131\u0132\7q\2\2\u0132\u0133\7p\2"+
"\2\u0133\u0134\7v\2\2\u0134\u0135\7k\2\2\u0135\u0136\7p\2\2\u0136\u0137"+
"\7w\2\2\u0137\u0138\7g\2\2\u0138\60\3\2\2\2\u0139\u013a\7c\2\2\u013a\u013b"+
"\7u\2\2\u013b\u013c\7o\2\2\u013c\62\3\2\2\2\u013d\u013e\7<\2\2\u013e\64"+
"\3\2\2\2\u013f\u0140\7\60\2\2\u0140\u0141\7\60\2\2\u0141\66\3\2\2\2\u0142"+
"\u0143\7u\2\2\u0143\u0144\7k\2\2\u0144\u0145\7i\2\2\u0145\u0146\7p\2\2"+
"\u0146\u0147\7g\2\2\u0147\u0148\7f\2\2\u01488\3\2\2\2\u0149\u014a\7,\2"+
"\2\u014a:\3\2\2\2\u014b\u014c\7]\2\2\u014c<\3\2\2\2\u014d\u014e\7_\2\2"+
"\u014e>\3\2\2\2\u014f\u0150\7/\2\2\u0150\u0151\7/\2\2\u0151@\3\2\2\2\u0152"+
"\u0153\7-\2\2\u0153\u0154\7-\2\2\u0154B\3\2\2\2\u0155\u0156\7-\2\2\u0156"+
"D\3\2\2\2\u0157\u0158\7/\2\2\u0158F\3\2\2\2\u0159\u015a\7#\2\2\u015aH"+
"\3\2\2\2\u015b\u015c\7(\2\2\u015cJ\3\2\2\2\u015d\u015e\7\u0080\2\2\u015e"+
"L\3\2\2\2\u015f\u0160\7@\2\2\u0160\u0161\7@\2\2\u0161N\3\2\2\2\u0162\u0163"+
"\7>\2\2\u0163\u0164\7>\2\2\u0164P\3\2\2\2\u0165\u0166\7\61\2\2\u0166R"+
"\3\2\2\2\u0167\u0168\7\'\2\2\u0168T\3\2\2\2\u0169\u016a\7>\2\2\u016aV"+
"\3\2\2\2\u016b\u016c\7@\2\2\u016cX\3\2\2\2\u016d\u016e\7?\2\2\u016e\u016f"+
"\7?\2\2\u016fZ\3\2\2\2\u0170\u0171\7#\2\2\u0171\u0172\7?\2\2\u0172\\\3"+
"\2\2\2\u0173\u0174\7>\2\2\u0174\u0175\7?\2\2\u0175^\3\2\2\2\u0176\u0177"+
"\7@\2\2\u0177\u0178\7?\2\2\u0178`\3\2\2\2\u0179\u017a\7`\2\2\u017ab\3"+
"\2\2\2\u017b\u017c\7~\2\2\u017cd\3\2\2\2\u017d\u017e\7(\2\2\u017e\u017f"+
"\7(\2\2\u017ff\3\2\2\2\u0180\u0181\7~\2\2\u0181\u0182\7~\2\2\u0182h\3"+
"\2\2\2\u0183\u0184\7-\2\2\u0184\u0185\7?\2\2\u0185j\3\2\2\2\u0186\u0187"+
"\7/\2\2\u0187\u0188\7?\2\2\u0188l\3\2\2\2\u0189\u018a\7,\2\2\u018a\u018b"+
"\7?\2\2\u018bn\3\2\2\2\u018c\u018d\7\61\2\2\u018d\u018e\7?\2\2\u018ep"+
"\3\2\2\2\u018f\u0190\7\'\2\2\u0190\u0191\7?\2\2\u0191r\3\2\2\2\u0192\u0193"+
"\7>\2\2\u0193\u0194\7>\2\2\u0194\u0195\7?\2\2\u0195t\3\2\2\2\u0196\u0197"+
"\7@\2\2\u0197\u0198\7@\2\2\u0198\u0199\7?\2\2\u0199v\3\2\2\2\u019a\u019b"+
"\7(\2\2\u019b\u019c\7?\2\2\u019cx\3\2\2\2\u019d\u019e\7~\2\2\u019e\u019f"+
"\7?\2\2\u019fz\3\2\2\2\u01a0\u01a1\7`\2\2\u01a1\u01a2\7?\2\2\u01a2|\3"+
"\2\2\2\u01a3\u01a4\7m\2\2\u01a4\u01a5\7k\2\2\u01a5\u01a6\7e\2\2\u01a6"+
"\u01a7\7m\2\2\u01a7\u01a8\7c\2\2\u01a8\u01a9\7u\2\2\u01a9\u01aa\7o\2\2"+
"\u01aa~\3\2\2\2\u01ab\u01ac\7t\2\2\u01ac\u01ad\7g\2\2\u01ad\u01ae\7u\2"+
"\2\u01ae\u01af\7q\2\2\u01af\u01b0\7w\2\2\u01b0\u01b1\7t\2\2\u01b1\u01b2"+
"\7e\2\2\u01b2\u01b3\7g\2\2\u01b3\u0080\3\2\2\2\u01b4\u01b5\7w\2\2\u01b5"+
"\u01b6\7u\2\2\u01b6\u01b7\7g\2\2\u01b7\u01b8\7u\2\2\u01b8\u0082\3\2\2"+
"\2\u01b9\u01ba\7e\2\2\u01ba\u01bb\7n\2\2\u01bb\u01bc\7q\2\2\u01bc\u01bd"+
"\7d\2\2\u01bd\u01be\7d\2\2\u01be\u01bf\7g\2\2\u01bf\u01c0\7t\2\2\u01c0"+
"\u01c1\7u\2\2\u01c1\u0084\3\2\2\2\u01c2\u01c3\7d\2\2\u01c3\u01c4\7{\2"+
"\2\u01c4\u01c5\7v\2\2\u01c5\u01c6\7g\2\2\u01c6\u01c7\7u\2\2\u01c7\u0086"+
"\3\2\2\2\u01c8\u01c9\7e\2\2\u01c9\u01ca\7{\2\2\u01ca\u01cb\7e\2\2\u01cb"+
"\u01cc\7n\2\2\u01cc\u01cd\7g\2\2\u01cd\u01ce\7u\2\2\u01ce\u0088\3\2\2"+
"\2\u01cf\u01d0\7r\2\2\u01d0\u01d1\7e\2\2\u01d1\u008a\3\2\2\2\u01d2\u01d3"+
"\7\60\2\2\u01d3\u01d4\7d\2\2\u01d4\u01d5\7{\2\2\u01d5\u01d6\7v\2\2\u01d6"+
"\u01d7\7g\2\2\u01d7\u008c\3\2\2\2\u01d8\u01d9\7%\2\2\u01d9\u008e\3\2\2"+
"\2\u01da\u01db\7\60\2\2\u01db\u0090\3\2\2\2\u01dc\u01dd\7d\2\2\u01dd\u01de"+
"\7t\2\2\u01de\u02bb\7m\2\2\u01df\u01e0\7q\2\2\u01e0\u01e1\7t\2\2\u01e1"+
"\u02bb\7c\2\2\u01e2\u01e3\7m\2\2\u01e3\u01e4\7k\2\2\u01e4\u02bb\7n\2\2"+
"\u01e5\u01e6\7u\2\2\u01e6\u01e7\7n\2\2\u01e7\u02bb\7q\2\2\u01e8\u01e9"+
"\7p\2\2\u01e9\u01ea\7q\2\2\u01ea\u02bb\7r\2\2\u01eb\u01ec\7c\2\2\u01ec"+
"\u01ed\7u\2\2\u01ed\u02bb\7n\2\2\u01ee\u01ef\7r\2\2\u01ef\u01f0\7j\2\2"+
"\u01f0\u02bb\7r\2\2\u01f1\u01f2\7c\2\2\u01f2\u01f3\7p\2\2\u01f3\u02bb"+
"\7e\2\2\u01f4\u01f5\7d\2\2\u01f5\u01f6\7r\2\2\u01f6\u02bb\7n\2\2\u01f7"+
"\u01f8\7e\2\2\u01f8\u01f9\7n\2\2\u01f9\u02bb\7e\2\2\u01fa\u01fb\7l\2\2"+
"\u01fb\u01fc\7u\2\2\u01fc\u02bb\7t\2\2\u01fd\u01fe\7c\2\2\u01fe\u01ff"+
"\7p\2\2\u01ff\u02bb\7f\2\2\u0200\u0201\7t\2\2\u0201\u0202\7n\2\2\u0202"+
"\u02bb\7c\2\2\u0203\u0204\7d\2\2\u0204\u0205\7k\2\2\u0205\u02bb\7v\2\2"+
"\u0206\u0207\7t\2\2\u0207\u0208\7q\2\2\u0208\u02bb\7n\2\2\u0209\u020a"+
"\7r\2\2\u020a\u020b\7n\2\2\u020b\u02bb\7c\2\2\u020c\u020d\7r\2\2\u020d"+
"\u020e\7n\2\2\u020e\u02bb\7r\2\2\u020f\u0210\7d\2\2\u0210\u0211\7o\2\2"+
"\u0211\u02bb\7k\2\2\u0212\u0213\7u\2\2\u0213\u0214\7g\2\2\u0214\u02bb"+
"\7e\2\2\u0215\u0216\7t\2\2\u0216\u0217\7v\2\2\u0217\u02bb\7k\2\2\u0218"+
"\u0219\7g\2\2\u0219\u021a\7q\2\2\u021a\u02bb\7t\2\2\u021b\u021c\7u\2\2"+
"\u021c\u021d\7t\2\2\u021d\u02bb\7g\2\2\u021e\u021f\7n\2\2\u021f\u0220"+
"\7u\2\2\u0220\u02bb\7t\2\2\u0221\u0222\7r\2\2\u0222\u0223\7j\2\2\u0223"+
"\u02bb\7c\2\2\u0224\u0225\7c\2\2\u0225\u0226\7n\2\2\u0226\u02bb\7t\2\2"+
"\u0227\u0228\7l\2\2\u0228\u0229\7o\2\2\u0229\u02bb\7r\2\2\u022a\u022b"+
"\7d\2\2\u022b\u022c\7x\2\2\u022c\u02bb\7e\2\2\u022d\u022e\7e\2\2\u022e"+
"\u022f\7n\2\2\u022f\u02bb\7k\2\2\u0230\u0231\7t\2\2\u0231\u0232\7v\2\2"+
"\u0232\u02bb\7u\2\2\u0233\u0234\7c\2\2\u0234\u0235\7f\2\2\u0235\u02bb"+
"\7e\2\2\u0236\u0237\7t\2\2\u0237\u0238\7t\2\2\u0238\u02bb\7c\2\2\u0239"+
"\u023a\7d\2\2\u023a\u023b\7x\2\2\u023b\u02bb\7u\2\2\u023c\u023d\7u\2\2"+
"\u023d\u023e\7g\2\2\u023e\u02bb\7k\2\2\u023f\u0240\7u\2\2\u0240\u0241"+
"\7c\2\2\u0241\u02bb\7z\2\2\u0242\u0243\7u\2\2\u0243\u0244\7v\2\2\u0244"+
"\u02bb\7{\2\2\u0245\u0246\7u\2\2\u0246\u0247\7v\2\2\u0247\u02bb\7c\2\2"+
"\u0248\u0249\7u\2\2\u0249\u024a\7v\2\2\u024a\u02bb\7z\2\2\u024b\u024c"+
"\7f\2\2\u024c\u024d\7g\2\2\u024d\u02bb\7{\2\2\u024e\u024f\7v\2\2\u024f"+
"\u0250\7z\2\2\u0250\u02bb\7c\2\2\u0251\u0252\7z\2\2\u0252\u0253\7c\2\2"+
"\u0253\u02bb\7c\2\2\u0254\u0255\7d\2\2\u0255\u0256\7e\2\2\u0256\u02bb"+
"\7e\2\2\u0257\u0258\7c\2\2\u0258\u0259\7j\2\2\u0259\u02bb\7z\2\2\u025a"+
"\u025b\7v\2\2\u025b\u025c\7{\2\2\u025c\u02bb\7c\2\2\u025d\u025e\7v\2\2"+
"\u025e\u025f\7z\2\2\u025f\u02bb\7u\2\2\u0260\u0261\7v\2\2\u0261\u0262"+
"\7c\2\2\u0262\u02bb\7u\2\2\u0263\u0264\7u\2\2\u0264\u0265\7j\2\2\u0265"+
"\u02bb\7{\2\2\u0266\u0267\7u\2\2\u0267\u0268\7j\2\2\u0268\u02bb\7z\2\2"+
"\u0269\u026a\7n\2\2\u026a\u026b\7f\2\2\u026b\u02bb\7{\2\2\u026c\u026d"+
"\7n\2\2\u026d\u026e\7f\2\2\u026e\u02bb\7c\2\2\u026f\u0270\7n\2\2\u0270"+
"\u0271\7f\2\2\u0271\u02bb\7z\2\2\u0272\u0273\7n\2\2\u0273\u0274\7c\2\2"+
"\u0274\u02bb\7z\2\2\u0275\u0276\7v\2\2\u0276\u0277\7c\2\2\u0277\u02bb"+
"\7{\2\2\u0278\u0279\7v\2\2\u0279\u027a\7c\2\2\u027a\u02bb\7z\2\2\u027b"+
"\u027c\7d\2\2\u027c\u027d\7e\2\2\u027d\u02bb\7u\2\2\u027e\u027f\7e\2\2"+
"\u027f\u0280\7n\2\2\u0280\u02bb\7x\2\2\u0281\u0282\7v\2\2\u0282\u0283"+
"\7u\2\2\u0283\u02bb\7z\2\2\u0284\u0285\7n\2\2\u0285\u0286\7c\2\2\u0286"+
"\u02bb\7u\2\2\u0287\u0288\7e\2\2\u0288\u0289\7r\2\2\u0289\u02bb\7{\2\2"+
"\u028a\u028b\7e\2\2\u028b\u028c\7o\2\2\u028c\u02bb\7r\2\2\u028d\u028e"+
"\7e\2\2\u028e\u028f\7r\2\2\u028f\u02bb\7z\2\2\u0290\u0291\7f\2\2\u0291"+
"\u0292\7e\2\2\u0292\u02bb\7r\2\2\u0293\u0294\7f\2\2\u0294\u0295\7g\2\2"+
"\u0295\u02bb\7e\2\2\u0296\u0297\7k\2\2\u0297\u0298\7p\2\2\u0298\u02bb"+
"\7e\2\2\u0299\u029a\7c\2\2\u029a\u029b\7z\2\2\u029b\u02bb\7u\2\2\u029c"+
"\u029d\7d\2\2\u029d\u029e\7p\2\2\u029e\u02bb\7g\2\2\u029f\u02a0\7e\2\2"+
"\u02a0\u02a1\7n\2\2\u02a1\u02bb\7f\2\2\u02a2\u02a3\7u\2\2\u02a3\u02a4"+
"\7d\2\2\u02a4\u02bb\7e\2\2\u02a5\u02a6\7k\2\2\u02a6\u02a7\7u\2\2\u02a7"+
"\u02bb\7e\2\2\u02a8\u02a9\7k\2\2\u02a9\u02aa\7p\2\2\u02aa\u02bb\7z\2\2"+
"\u02ab\u02ac\7d\2\2\u02ac\u02ad\7g\2\2\u02ad\u02bb\7s\2\2\u02ae\u02af"+
"\7u\2\2\u02af\u02b0\7g\2\2\u02b0\u02bb\7f\2\2\u02b1\u02b2\7f\2\2\u02b2"+
"\u02b3\7g\2\2\u02b3\u02bb\7z\2\2\u02b4\u02b5\7k\2\2\u02b5\u02b6\7p\2\2"+
"\u02b6\u02bb\7{\2\2\u02b7\u02b8\7t\2\2\u02b8\u02b9\7q\2\2\u02b9\u02bb"+
"\7t\2\2\u02ba\u01dc\3\2\2\2\u02ba\u01df\3\2\2\2\u02ba\u01e2\3\2\2\2\u02ba"+
"\u01e5\3\2\2\2\u02ba\u01e8\3\2\2\2\u02ba\u01eb\3\2\2\2\u02ba\u01ee\3\2"+
"\2\2\u02ba\u01f1\3\2\2\2\u02ba\u01f4\3\2\2\2\u02ba\u01f7\3\2\2\2\u02ba"+
"\u01fa\3\2\2\2\u02ba\u01fd\3\2\2\2\u02ba\u0200\3\2\2\2\u02ba\u0203\3\2"+
"\2\2\u02ba\u0206\3\2\2\2\u02ba\u0209\3\2\2\2\u02ba\u020c\3\2\2\2\u02ba"+
"\u020f\3\2\2\2\u02ba\u0212\3\2\2\2\u02ba\u0215\3\2\2\2\u02ba\u0218\3\2"+
"\2\2\u02ba\u021b\3\2\2\2\u02ba\u021e\3\2\2\2\u02ba\u0221\3\2\2\2\u02ba"+
"\u0224\3\2\2\2\u02ba\u0227\3\2\2\2\u02ba\u022a\3\2\2\2\u02ba\u022d\3\2"+
"\2\2\u02ba\u0230\3\2\2\2\u02ba\u0233\3\2\2\2\u02ba\u0236\3\2\2\2\u02ba"+
"\u0239\3\2\2\2\u02ba\u023c\3\2\2\2\u02ba\u023f\3\2\2\2\u02ba\u0242\3\2"+
"\2\2\u02ba\u0245\3\2\2\2\u02ba\u0248\3\2\2\2\u02ba\u024b\3\2\2\2\u02ba"+
"\u024e\3\2\2\2\u02ba\u0251\3\2\2\2\u02ba\u0254\3\2\2\2\u02ba\u0257\3\2"+
"\2\2\u02ba\u025a\3\2\2\2\u02ba\u025d\3\2\2\2\u02ba\u0260\3\2\2\2\u02ba"+
"\u0263\3\2\2\2\u02ba\u0266\3\2\2\2\u02ba\u0269\3\2\2\2\u02ba\u026c\3\2"+
"\2\2\u02ba\u026f\3\2\2\2\u02ba\u0272\3\2\2\2\u02ba\u0275\3\2\2\2\u02ba"+
"\u0278\3\2\2\2\u02ba\u027b\3\2\2\2\u02ba\u027e\3\2\2\2\u02ba\u0281\3\2"+
"\2\2\u02ba\u0284\3\2\2\2\u02ba\u0287\3\2\2\2\u02ba\u028a\3\2\2\2\u02ba"+
"\u028d\3\2\2\2\u02ba\u0290\3\2\2\2\u02ba\u0293\3\2\2\2\u02ba\u0296\3\2"+
"\2\2\u02ba\u0299\3\2\2\2\u02ba\u029c\3\2\2\2\u02ba\u029f\3\2\2\2\u02ba"+
"\u02a2\3\2\2\2\u02ba\u02a5\3\2\2\2\u02ba\u02a8\3\2\2\2\u02ba\u02ab\3\2"+
"\2\2\u02ba\u02ae\3\2\2\2\u02ba\u02b1\3\2\2\2\u02ba\u02b4\3\2\2\2\u02ba"+
"\u02b7\3\2\2\2\u02bb\u0092\3\2\2\2\u02bc\u02bd\7}\2\2\u02bd\u02be\7}\2"+
"\2\u02be\u02c2\3\2\2\2\u02bf\u02c1\13\2\2\2\u02c0\u02bf\3\2\2\2\u02c1"+
"\u02c4\3\2\2\2\u02c2\u02c3\3\2\2\2\u02c2\u02c0\3\2\2\2\u02c3\u02c5\3\2"+
"\2\2\u02c4\u02c2\3\2\2\2\u02c5\u02c6\7\177\2\2\u02c6\u02c7\7\177\2\2\u02c7"+
"\u0094\3\2\2\2\u02c8\u02c9\7d\2\2\u02c9\u02ca\7{\2\2\u02ca\u02cb\7v\2"+
"\2\u02cb\u02de\7g\2\2\u02cc\u02cd\7y\2\2\u02cd\u02ce\7q\2\2\u02ce\u02cf"+
"\7t\2\2\u02cf\u02de\7f\2\2\u02d0\u02d1\7f\2\2\u02d1\u02d2\7y\2\2\u02d2"+
"\u02d3\7q\2\2\u02d3\u02d4\7t\2\2\u02d4\u02de\7f\2\2\u02d5\u02d6\7d\2\2"+
"\u02d6\u02d7\7q\2\2\u02d7\u02d8\7q\2\2\u02d8\u02de\7n\2\2\u02d9\u02da"+
"\7x\2\2\u02da\u02db\7q\2\2\u02db\u02dc\7k\2\2\u02dc\u02de\7f\2\2\u02dd"+
"\u02c8\3\2\2\2\u02dd\u02cc\3\2\2\2\u02dd\u02d0\3\2\2\2\u02dd\u02d5\3\2"+
"\2\2\u02dd\u02d9\3\2\2\2\u02de\u0096\3\2\2\2\u02df\u02e5\7$\2\2\u02e0"+
"\u02e1\7^\2\2\u02e1\u02e4\7$\2\2\u02e2\u02e4\n\2\2\2\u02e3\u02e0\3\2\2"+
"\2\u02e3\u02e2\3\2\2\2\u02e4\u02e7\3\2\2\2\u02e5\u02e3\3\2\2\2\u02e5\u02e6"+
"\3\2\2\2\u02e6\u02e8\3\2\2\2\u02e7\u02e5\3\2\2\2\u02e8\u02e9\7$\2\2\u02e9"+
"\u0098\3\2\2\2\u02ea\u02ee\7)\2\2\u02eb\u02ec\7^\2\2\u02ec\u02ef\7)\2"+
"\2\u02ed\u02ef\n\3\2\2\u02ee\u02eb\3\2\2\2\u02ee\u02ed\3\2\2\2\u02ef\u02f0"+
"\3\2\2\2\u02f0\u02f1\7)\2\2\u02f1\u009a\3\2\2\2\u02f2\u02f3\7v\2\2\u02f3"+
"\u02f4\7t\2\2\u02f4\u02f5\7w\2\2\u02f5\u02fc\7g\2\2\u02f6\u02f7\7h\2\2"+
"\u02f7\u02f8\7c\2\2\u02f8\u02f9\7n\2\2\u02f9\u02fa\7u\2\2\u02fa\u02fc"+
"\7g\2\2\u02fb\u02f2\3\2\2\2\u02fb\u02f6\3\2\2\2\u02fc\u009c\3\2\2\2\u02fd"+
"\u0300\5\u009fP\2\u02fe\u0300\5\u00a7T\2\u02ff\u02fd\3\2\2\2\u02ff\u02fe"+
"\3\2\2\2\u0300\u009e\3\2\2\2\u0301\u0305\5\u00a1Q\2\u0302\u0305\5\u00a3"+
"R\2\u0303\u0305\5\u00a5S\2\u0304\u0301\3\2\2\2\u0304\u0302\3\2\2\2\u0304"+
"\u0303\3\2\2\2\u0305\u00a0\3\2\2\2\u0306\u030c\7\'\2\2\u0307\u0308\7\62"+
"\2\2\u0308\u030c\7d\2\2\u0309\u030a\7\62\2\2\u030a\u030c\7D\2\2\u030b"+
"\u0306\3\2\2\2\u030b\u0307\3\2\2\2\u030b\u0309\3\2\2\2\u030c\u0310\3\2"+
"\2\2\u030d\u030f\5\u00afX\2\u030e\u030d\3\2\2\2\u030f\u0312\3\2\2\2\u0310"+
"\u030e\3\2\2\2\u0310\u0311\3\2\2\2\u0311\u0313\3\2\2\2\u0312\u0310\3\2"+
"\2\2\u0313\u0315\7\60\2\2\u0314\u0316\5\u00afX\2\u0315\u0314\3\2\2\2\u0316"+
"\u0317\3\2\2\2\u0317\u0315\3\2\2\2\u0317\u0318\3\2\2\2\u0318\u00a2\3\2"+
"\2\2\u0319\u031b\5\u00b1Y\2\u031a\u0319\3\2\2\2\u031b\u031e\3\2\2\2\u031c"+
"\u031a\3\2\2\2\u031c\u031d\3\2\2\2\u031d\u031f\3\2\2\2\u031e\u031c\3\2"+
"\2\2\u031f\u0321\7\60\2\2\u0320\u0322\5\u00b1Y\2\u0321\u0320\3\2\2\2\u0322"+
"\u0323\3\2\2\2\u0323\u0321\3\2\2\2\u0323\u0324\3\2\2\2\u0324\u00a4\3\2"+
"\2\2\u0325\u032b\7&\2\2\u0326\u0327\7\62\2\2\u0327\u032b\7z\2\2\u0328"+
"\u0329\7\62\2\2\u0329\u032b\7Z\2\2\u032a\u0325\3\2\2\2\u032a\u0326\3\2"+
"\2\2\u032a\u0328\3\2\2\2\u032b\u032f\3\2\2\2\u032c\u032e\5\u00b3Z\2\u032d"+
"\u032c\3\2\2\2\u032e\u0331\3\2\2\2\u032f\u032d\3\2\2\2\u032f\u0330\3\2"+
"\2\2\u0330\u0332\3\2\2\2\u0331\u032f\3\2\2\2\u0332\u0334\7\60\2\2\u0333"+
"\u0335\5\u00b3Z\2\u0334\u0333\3\2\2\2\u0335\u0336\3\2\2\2\u0336\u0334"+
"\3\2\2\2\u0336\u0337\3\2\2\2\u0337\u00a6\3\2\2\2\u0338\u033c\5\u00abV"+
"\2\u0339\u033c\5\u00adW\2\u033a\u033c\5\u00a9U\2\u033b\u0338\3\2\2\2\u033b"+
"\u0339\3\2\2\2\u033b\u033a\3\2\2\2\u033c\u00a8\3\2\2\2\u033d\u033e\7\62"+
"\2\2\u033e\u0340\t\4\2\2\u033f\u0341\5\u00afX\2\u0340\u033f\3\2\2\2\u0341"+
"\u0342\3\2\2\2\u0342\u0340\3\2\2\2\u0342\u0343\3\2\2\2\u0343\u034b\3\2"+
"\2\2\u0344\u0346\7\'\2\2\u0345\u0347\5\u00afX\2\u0346\u0345\3\2\2\2\u0347"+
"\u0348\3\2\2\2\u0348\u0346\3\2\2\2\u0348\u0349\3\2\2\2\u0349\u034b\3\2"+
"\2\2\u034a\u033d\3\2\2\2\u034a\u0344\3\2\2\2\u034b\u00aa\3\2\2\2\u034c"+
"\u034e\5\u00b1Y\2\u034d\u034c\3\2\2\2\u034e\u034f\3\2\2\2\u034f\u034d"+
"\3\2\2\2\u034f\u0350\3\2\2\2\u0350\u00ac\3\2\2\2\u0351\u0357\7&\2\2\u0352"+
"\u0353\7\62\2\2\u0353\u0357\7z\2\2\u0354\u0355\7\62\2\2\u0355\u0357\7"+
"Z\2\2\u0356\u0351\3\2\2\2\u0356\u0352\3\2\2\2\u0356\u0354\3\2\2\2\u0357"+
"\u0359\3\2\2\2\u0358\u035a\5\u00b3Z\2\u0359\u0358\3\2\2\2\u035a\u035b"+
"\3\2\2\2\u035b\u0359\3\2\2\2\u035b\u035c\3\2\2\2\u035c\u00ae\3\2\2\2\u035d"+
"\u035e\t\5\2\2\u035e\u00b0\3\2\2\2\u035f\u0360\t\6\2\2\u0360\u00b2\3\2"+
"\2\2\u0361\u0362\t\7\2\2\u0362\u00b4\3\2\2\2\u0363\u0367\5\u00b7\\\2\u0364"+
"\u0366\5\u00b9]\2\u0365\u0364\3\2\2\2\u0366\u0369\3\2\2\2\u0367\u0365"+
"\3\2\2\2\u0367\u0368\3\2\2\2\u0368\u00b6\3\2\2\2\u0369\u0367\3\2\2\2\u036a"+
"\u036b\t\b\2\2\u036b\u00b8\3\2\2\2\u036c\u036d\t\t\2\2\u036d\u00ba\3\2"+
"\2\2\u036e\u0372\7#\2\2\u036f\u0371\5\u00b9]\2\u0370\u036f\3\2\2\2\u0371"+
"\u0374\3\2\2\2\u0372\u0370\3\2\2\2\u0372\u0373\3\2\2\2\u0373\u0376\3\2"+
"\2\2\u0374\u0372\3\2\2\2\u0375\u0377\t\n\2\2\u0376\u0375\3\2\2\2\u0377"+
"\u0378\3\2\2\2\u0378\u0376\3\2\2\2\u0378\u0379\3\2\2\2\u0379\u00bc\3\2"+
"\2\2\u037a\u037c\t\13\2\2\u037b\u037a\3\2\2\2\u037c\u037d\3\2\2\2\u037d"+
"\u037b\3\2\2\2\u037d\u037e\3\2\2\2\u037e\u037f\3\2\2\2\u037f\u0380\b_"+
"\2\2\u0380\u00be\3\2\2\2\u0381\u0382\7\61\2\2\u0382\u0383\7\61\2\2\u0383"+
"\u0387\3\2\2\2\u0384\u0386\n\f\2\2\u0385\u0384\3\2\2\2\u0386\u0389\3\2"+
"\2\2\u0387\u0385\3\2\2\2\u0387\u0388\3\2\2\2\u0388\u038a\3\2\2\2\u0389"+
"\u0387\3\2\2\2\u038a\u038b\b`\3\2\u038b\u00c0\3\2\2\2\u038c\u038d\7\61"+
"\2\2\u038d\u038e\7,\2\2\u038e\u0392\3\2\2\2\u038f\u0391\13\2\2\2\u0390"+
"\u038f\3\2\2\2\u0391\u0394\3\2\2\2\u0392\u0393\3\2\2\2\u0392\u0390\3\2"+
"\2\2\u0393\u0395\3\2\2\2\u0394\u0392\3\2\2\2\u0395\u0396\7,\2\2\u0396"+
"\u0397\7\61\2\2\u0397\u0398\3\2\2\2\u0398\u0399\ba\3\2\u0399\u00c2\3\2"+
"\2\2!\2\u02ba\u02c2\u02dd\u02e3\u02e5\u02ee\u02fb\u02ff\u0304\u030b\u0310"+
"\u0317\u031c\u0323\u032a\u032f\u0336\u033b\u0342\u0348\u034a\u034f\u0356"+
"\u035b\u0367\u0372\u0378\u037d\u0387\u0392\4\2\3\2\2\4\2";
"Y\u00b1\2\u00b3\2\u00b5\2\u00b7Z\u00b9\2\u00bb\2\u00bd[\u00bf\\\u00c1"+
"]\u00c3^\3\2\r\3\2$$\3\2))\4\2DDdd\3\2\62\63\3\2\62;\5\2\62;CHch\5\2C"+
"\\aac|\6\2\62;C\\aac|\4\2--//\6\2\13\f\17\17\"\"\u00a2\u00a2\4\2\f\f\17"+
"\17\2\u0406\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2"+
"\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27"+
"\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2"+
"\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2"+
"\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2"+
"\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2"+
"\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2\2\2\2S"+
"\3\2\2\2\2U\3\2\2\2\2W\3\2\2\2\2Y\3\2\2\2\2[\3\2\2\2\2]\3\2\2\2\2_\3\2"+
"\2\2\2a\3\2\2\2\2c\3\2\2\2\2e\3\2\2\2\2g\3\2\2\2\2i\3\2\2\2\2k\3\2\2\2"+
"\2m\3\2\2\2\2o\3\2\2\2\2q\3\2\2\2\2s\3\2\2\2\2u\3\2\2\2\2w\3\2\2\2\2y"+
"\3\2\2\2\2{\3\2\2\2\2}\3\2\2\2\2\177\3\2\2\2\2\u0081\3\2\2\2\2\u0083\3"+
"\2\2\2\2\u0085\3\2\2\2\2\u0087\3\2\2\2\2\u0089\3\2\2\2\2\u008b\3\2\2\2"+
"\2\u008d\3\2\2\2\2\u008f\3\2\2\2\2\u0091\3\2\2\2\2\u0093\3\2\2\2\2\u0095"+
"\3\2\2\2\2\u0097\3\2\2\2\2\u0099\3\2\2\2\2\u009b\3\2\2\2\2\u009d\3\2\2"+
"\2\2\u009f\3\2\2\2\2\u00a1\3\2\2\2\2\u00a3\3\2\2\2\2\u00a5\3\2\2\2\2\u00a7"+
"\3\2\2\2\2\u00a9\3\2\2\2\2\u00ab\3\2\2\2\2\u00ad\3\2\2\2\2\u00af\3\2\2"+
"\2\2\u00b7\3\2\2\2\2\u00bd\3\2\2\2\2\u00bf\3\2\2\2\2\u00c1\3\2\2\2\2\u00c3"+
"\3\2\2\2\3\u00c5\3\2\2\2\5\u00cc\3\2\2\2\7\u00ce\3\2\2\2\t\u00d0\3\2\2"+
"\2\13\u00d2\3\2\2\2\r\u00d4\3\2\2\2\17\u00d6\3\2\2\2\21\u00d8\3\2\2\2"+
"\23\u00da\3\2\2\2\25\u00e0\3\2\2\2\27\u00e7\3\2\2\2\31\u00ed\3\2\2\2\33"+
"\u00f6\3\2\2\2\35\u00fd\3\2\2\2\37\u0106\3\2\2\2!\u0110\3\2\2\2#\u0113"+
"\3\2\2\2%\u0118\3\2\2\2\'\u011e\3\2\2\2)\u0121\3\2\2\2+\u0125\3\2\2\2"+
"-\u012c\3\2\2\2/\u0132\3\2\2\2\61\u013b\3\2\2\2\63\u013f\3\2\2\2\65\u0141"+
"\3\2\2\2\67\u0144\3\2\2\29\u014b\3\2\2\2;\u014d\3\2\2\2=\u014f\3\2\2\2"+
"?\u0151\3\2\2\2A\u0154\3\2\2\2C\u0157\3\2\2\2E\u0159\3\2\2\2G\u015b\3"+
"\2\2\2I\u015d\3\2\2\2K\u015f\3\2\2\2M\u0161\3\2\2\2O\u0164\3\2\2\2Q\u0167"+
"\3\2\2\2S\u0169\3\2\2\2U\u016b\3\2\2\2W\u016d\3\2\2\2Y\u016f\3\2\2\2["+
"\u0172\3\2\2\2]\u0175\3\2\2\2_\u0178\3\2\2\2a\u017b\3\2\2\2c\u017d\3\2"+
"\2\2e\u017f\3\2\2\2g\u0182\3\2\2\2i\u0185\3\2\2\2k\u0187\3\2\2\2m\u018a"+
"\3\2\2\2o\u018d\3\2\2\2q\u0190\3\2\2\2s\u0193\3\2\2\2u\u0196\3\2\2\2w"+
"\u019a\3\2\2\2y\u019e\3\2\2\2{\u01a1\3\2\2\2}\u01a4\3\2\2\2\177\u01a7"+
"\3\2\2\2\u0081\u01af\3\2\2\2\u0083\u01b8\3\2\2\2\u0085\u01bd\3\2\2\2\u0087"+
"\u01c6\3\2\2\2\u0089\u01cc\3\2\2\2\u008b\u01d3\3\2\2\2\u008d\u01d6\3\2"+
"\2\2\u008f\u01dc\3\2\2\2\u0091\u01de\3\2\2\2\u0093\u02be\3\2\2\2\u0095"+
"\u02c0\3\2\2\2\u0097\u02e1\3\2\2\2\u0099\u02e3\3\2\2\2\u009b\u02ee\3\2"+
"\2\2\u009d\u02ff\3\2\2\2\u009f\u0303\3\2\2\2\u00a1\u0308\3\2\2\2\u00a3"+
"\u030f\3\2\2\2\u00a5\u0320\3\2\2\2\u00a7\u032e\3\2\2\2\u00a9\u033f\3\2"+
"\2\2\u00ab\u034e\3\2\2\2\u00ad\u0351\3\2\2\2\u00af\u035a\3\2\2\2\u00b1"+
"\u0361\3\2\2\2\u00b3\u0363\3\2\2\2\u00b5\u0365\3\2\2\2\u00b7\u0367\3\2"+
"\2\2\u00b9\u036e\3\2\2\2\u00bb\u0370\3\2\2\2\u00bd\u0372\3\2\2\2\u00bf"+
"\u037f\3\2\2\2\u00c1\u0385\3\2\2\2\u00c3\u0390\3\2\2\2\u00c5\u00c6\7k"+
"\2\2\u00c6\u00c7\7o\2\2\u00c7\u00c8\7r\2\2\u00c8\u00c9\7q\2\2\u00c9\u00ca"+
"\7t\2\2\u00ca\u00cb\7v\2\2\u00cb\4\3\2\2\2\u00cc\u00cd\7?\2\2\u00cd\6"+
"\3\2\2\2\u00ce\u00cf\7=\2\2\u00cf\b\3\2\2\2\u00d0\u00d1\7*\2\2\u00d1\n"+
"\3\2\2\2\u00d2\u00d3\7+\2\2\u00d3\f\3\2\2\2\u00d4\u00d5\7}\2\2\u00d5\16"+
"\3\2\2\2\u00d6\u00d7\7\177\2\2\u00d7\20\3\2\2\2\u00d8\u00d9\7.\2\2\u00d9"+
"\22\3\2\2\2\u00da\u00db\7e\2\2\u00db\u00dc\7q\2\2\u00dc\u00dd\7p\2\2\u00dd"+
"\u00de\7u\2\2\u00de\u00df\7v\2\2\u00df\24\3\2\2\2\u00e0\u00e1\7g\2\2\u00e1"+
"\u00e2\7z\2\2\u00e2\u00e3\7v\2\2\u00e3\u00e4\7g\2\2\u00e4\u00e5\7t\2\2"+
"\u00e5\u00e6\7p\2\2\u00e6\26\3\2\2\2\u00e7\u00e8\7c\2\2\u00e8\u00e9\7"+
"n\2\2\u00e9\u00ea\7k\2\2\u00ea\u00eb\7i\2\2\u00eb\u00ec\7p\2\2\u00ec\30"+
"\3\2\2\2\u00ed\u00ee\7t\2\2\u00ee\u00ef\7g\2\2\u00ef\u00f0\7i\2\2\u00f0"+
"\u00f1\7k\2\2\u00f1\u00f2\7u\2\2\u00f2\u00f3\7v\2\2\u00f3\u00f4\7g\2\2"+
"\u00f4\u00f5\7t\2\2\u00f5\32\3\2\2\2\u00f6\u00f7\7k\2\2\u00f7\u00f8\7"+
"p\2\2\u00f8\u00f9\7n\2\2\u00f9\u00fa\7k\2\2\u00fa\u00fb\7p\2\2\u00fb\u00fc"+
"\7g\2\2\u00fc\34\3\2\2\2\u00fd\u00fe\7x\2\2\u00fe\u00ff\7q\2\2\u00ff\u0100"+
"\7n\2\2\u0100\u0101\7c\2\2\u0101\u0102\7v\2\2\u0102\u0103\7k\2\2\u0103"+
"\u0104\7n\2\2\u0104\u0105\7g\2\2\u0105\36\3\2\2\2\u0106\u0107\7k\2\2\u0107"+
"\u0108\7p\2\2\u0108\u0109\7v\2\2\u0109\u010a\7g\2\2\u010a\u010b\7t\2\2"+
"\u010b\u010c\7t\2\2\u010c\u010d\7w\2\2\u010d\u010e\7r\2\2\u010e\u010f"+
"\7v\2\2\u010f \3\2\2\2\u0110\u0111\7k\2\2\u0111\u0112\7h\2\2\u0112\"\3"+
"\2\2\2\u0113\u0114\7g\2\2\u0114\u0115\7n\2\2\u0115\u0116\7u\2\2\u0116"+
"\u0117\7g\2\2\u0117$\3\2\2\2\u0118\u0119\7y\2\2\u0119\u011a\7j\2\2\u011a"+
"\u011b\7k\2\2\u011b\u011c\7n\2\2\u011c\u011d\7g\2\2\u011d&\3\2\2\2\u011e"+
"\u011f\7f\2\2\u011f\u0120\7q\2\2\u0120(\3\2\2\2\u0121\u0122\7h\2\2\u0122"+
"\u0123\7q\2\2\u0123\u0124\7t\2\2\u0124*\3\2\2\2\u0125\u0126\7t\2\2\u0126"+
"\u0127\7g\2\2\u0127\u0128\7v\2\2\u0128\u0129\7w\2\2\u0129\u012a\7t\2\2"+
"\u012a\u012b\7p\2\2\u012b,\3\2\2\2\u012c\u012d\7d\2\2\u012d\u012e\7t\2"+
"\2\u012e\u012f\7g\2\2\u012f\u0130\7c\2\2\u0130\u0131\7m\2\2\u0131.\3\2"+
"\2\2\u0132\u0133\7e\2\2\u0133\u0134\7q\2\2\u0134\u0135\7p\2\2\u0135\u0136"+
"\7v\2\2\u0136\u0137\7k\2\2\u0137\u0138\7p\2\2\u0138\u0139\7w\2\2\u0139"+
"\u013a\7g\2\2\u013a\60\3\2\2\2\u013b\u013c\7c\2\2\u013c\u013d\7u\2\2\u013d"+
"\u013e\7o\2\2\u013e\62\3\2\2\2\u013f\u0140\7<\2\2\u0140\64\3\2\2\2\u0141"+
"\u0142\7\60\2\2\u0142\u0143\7\60\2\2\u0143\66\3\2\2\2\u0144\u0145\7u\2"+
"\2\u0145\u0146\7k\2\2\u0146\u0147\7i\2\2\u0147\u0148\7p\2\2\u0148\u0149"+
"\7g\2\2\u0149\u014a\7f\2\2\u014a8\3\2\2\2\u014b\u014c\7,\2\2\u014c:\3"+
"\2\2\2\u014d\u014e\7]\2\2\u014e<\3\2\2\2\u014f\u0150\7_\2\2\u0150>\3\2"+
"\2\2\u0151\u0152\7/\2\2\u0152\u0153\7/\2\2\u0153@\3\2\2\2\u0154\u0155"+
"\7-\2\2\u0155\u0156\7-\2\2\u0156B\3\2\2\2\u0157\u0158\7-\2\2\u0158D\3"+
"\2\2\2\u0159\u015a\7/\2\2\u015aF\3\2\2\2\u015b\u015c\7#\2\2\u015cH\3\2"+
"\2\2\u015d\u015e\7(\2\2\u015eJ\3\2\2\2\u015f\u0160\7\u0080\2\2\u0160L"+
"\3\2\2\2\u0161\u0162\7@\2\2\u0162\u0163\7@\2\2\u0163N\3\2\2\2\u0164\u0165"+
"\7>\2\2\u0165\u0166\7>\2\2\u0166P\3\2\2\2\u0167\u0168\7\61\2\2\u0168R"+
"\3\2\2\2\u0169\u016a\7\'\2\2\u016aT\3\2\2\2\u016b\u016c\7>\2\2\u016cV"+
"\3\2\2\2\u016d\u016e\7@\2\2\u016eX\3\2\2\2\u016f\u0170\7?\2\2\u0170\u0171"+
"\7?\2\2\u0171Z\3\2\2\2\u0172\u0173\7#\2\2\u0173\u0174\7?\2\2\u0174\\\3"+
"\2\2\2\u0175\u0176\7>\2\2\u0176\u0177\7?\2\2\u0177^\3\2\2\2\u0178\u0179"+
"\7@\2\2\u0179\u017a\7?\2\2\u017a`\3\2\2\2\u017b\u017c\7`\2\2\u017cb\3"+
"\2\2\2\u017d\u017e\7~\2\2\u017ed\3\2\2\2\u017f\u0180\7(\2\2\u0180\u0181"+
"\7(\2\2\u0181f\3\2\2\2\u0182\u0183\7~\2\2\u0183\u0184\7~\2\2\u0184h\3"+
"\2\2\2\u0185\u0186\7A\2\2\u0186j\3\2\2\2\u0187\u0188\7-\2\2\u0188\u0189"+
"\7?\2\2\u0189l\3\2\2\2\u018a\u018b\7/\2\2\u018b\u018c\7?\2\2\u018cn\3"+
"\2\2\2\u018d\u018e\7,\2\2\u018e\u018f\7?\2\2\u018fp\3\2\2\2\u0190\u0191"+
"\7\61\2\2\u0191\u0192\7?\2\2\u0192r\3\2\2\2\u0193\u0194\7\'\2\2\u0194"+
"\u0195\7?\2\2\u0195t\3\2\2\2\u0196\u0197\7>\2\2\u0197\u0198\7>\2\2\u0198"+
"\u0199\7?\2\2\u0199v\3\2\2\2\u019a\u019b\7@\2\2\u019b\u019c\7@\2\2\u019c"+
"\u019d\7?\2\2\u019dx\3\2\2\2\u019e\u019f\7(\2\2\u019f\u01a0\7?\2\2\u01a0"+
"z\3\2\2\2\u01a1\u01a2\7~\2\2\u01a2\u01a3\7?\2\2\u01a3|\3\2\2\2\u01a4\u01a5"+
"\7`\2\2\u01a5\u01a6\7?\2\2\u01a6~\3\2\2\2\u01a7\u01a8\7m\2\2\u01a8\u01a9"+
"\7k\2\2\u01a9\u01aa\7e\2\2\u01aa\u01ab\7m\2\2\u01ab\u01ac\7c\2\2\u01ac"+
"\u01ad\7u\2\2\u01ad\u01ae\7o\2\2\u01ae\u0080\3\2\2\2\u01af\u01b0\7t\2"+
"\2\u01b0\u01b1\7g\2\2\u01b1\u01b2\7u\2\2\u01b2\u01b3\7q\2\2\u01b3\u01b4"+
"\7w\2\2\u01b4\u01b5\7t\2\2\u01b5\u01b6\7e\2\2\u01b6\u01b7\7g\2\2\u01b7"+
"\u0082\3\2\2\2\u01b8\u01b9\7w\2\2\u01b9\u01ba\7u\2\2\u01ba\u01bb\7g\2"+
"\2\u01bb\u01bc\7u\2\2\u01bc\u0084\3\2\2\2\u01bd\u01be\7e\2\2\u01be\u01bf"+
"\7n\2\2\u01bf\u01c0\7q\2\2\u01c0\u01c1\7d\2\2\u01c1\u01c2\7d\2\2\u01c2"+
"\u01c3\7g\2\2\u01c3\u01c4\7t\2\2\u01c4\u01c5\7u\2\2\u01c5\u0086\3\2\2"+
"\2\u01c6\u01c7\7d\2\2\u01c7\u01c8\7{\2\2\u01c8\u01c9\7v\2\2\u01c9\u01ca"+
"\7g\2\2\u01ca\u01cb\7u\2\2\u01cb\u0088\3\2\2\2\u01cc\u01cd\7e\2\2\u01cd"+
"\u01ce\7{\2\2\u01ce\u01cf\7e\2\2\u01cf\u01d0\7n\2\2\u01d0\u01d1\7g\2\2"+
"\u01d1\u01d2\7u\2\2\u01d2\u008a\3\2\2\2\u01d3\u01d4\7r\2\2\u01d4\u01d5"+
"\7e\2\2\u01d5\u008c\3\2\2\2\u01d6\u01d7\7\60\2\2\u01d7\u01d8\7d\2\2\u01d8"+
"\u01d9\7{\2\2\u01d9\u01da\7v\2\2\u01da\u01db\7g\2\2\u01db\u008e\3\2\2"+
"\2\u01dc\u01dd\7%\2\2\u01dd\u0090\3\2\2\2\u01de\u01df\7\60\2\2\u01df\u0092"+
"\3\2\2\2\u01e0\u01e1\7d\2\2\u01e1\u01e2\7t\2\2\u01e2\u02bf\7m\2\2\u01e3"+
"\u01e4\7q\2\2\u01e4\u01e5\7t\2\2\u01e5\u02bf\7c\2\2\u01e6\u01e7\7m\2\2"+
"\u01e7\u01e8\7k\2\2\u01e8\u02bf\7n\2\2\u01e9\u01ea\7u\2\2\u01ea\u01eb"+
"\7n\2\2\u01eb\u02bf\7q\2\2\u01ec\u01ed\7p\2\2\u01ed\u01ee\7q\2\2\u01ee"+
"\u02bf\7r\2\2\u01ef\u01f0\7c\2\2\u01f0\u01f1\7u\2\2\u01f1\u02bf\7n\2\2"+
"\u01f2\u01f3\7r\2\2\u01f3\u01f4\7j\2\2\u01f4\u02bf\7r\2\2\u01f5\u01f6"+
"\7c\2\2\u01f6\u01f7\7p\2\2\u01f7\u02bf\7e\2\2\u01f8\u01f9\7d\2\2\u01f9"+
"\u01fa\7r\2\2\u01fa\u02bf\7n\2\2\u01fb\u01fc\7e\2\2\u01fc\u01fd\7n\2\2"+
"\u01fd\u02bf\7e\2\2\u01fe\u01ff\7l\2\2\u01ff\u0200\7u\2\2\u0200\u02bf"+
"\7t\2\2\u0201\u0202\7c\2\2\u0202\u0203\7p\2\2\u0203\u02bf\7f\2\2\u0204"+
"\u0205\7t\2\2\u0205\u0206\7n\2\2\u0206\u02bf\7c\2\2\u0207\u0208\7d\2\2"+
"\u0208\u0209\7k\2\2\u0209\u02bf\7v\2\2\u020a\u020b\7t\2\2\u020b\u020c"+
"\7q\2\2\u020c\u02bf\7n\2\2\u020d\u020e\7r\2\2\u020e\u020f\7n\2\2\u020f"+
"\u02bf\7c\2\2\u0210\u0211\7r\2\2\u0211\u0212\7n\2\2\u0212\u02bf\7r\2\2"+
"\u0213\u0214\7d\2\2\u0214\u0215\7o\2\2\u0215\u02bf\7k\2\2\u0216\u0217"+
"\7u\2\2\u0217\u0218\7g\2\2\u0218\u02bf\7e\2\2\u0219\u021a\7t\2\2\u021a"+
"\u021b\7v\2\2\u021b\u02bf\7k\2\2\u021c\u021d\7g\2\2\u021d\u021e\7q\2\2"+
"\u021e\u02bf\7t\2\2\u021f\u0220\7u\2\2\u0220\u0221\7t\2\2\u0221\u02bf"+
"\7g\2\2\u0222\u0223\7n\2\2\u0223\u0224\7u\2\2\u0224\u02bf\7t\2\2\u0225"+
"\u0226\7r\2\2\u0226\u0227\7j\2\2\u0227\u02bf\7c\2\2\u0228\u0229\7c\2\2"+
"\u0229\u022a\7n\2\2\u022a\u02bf\7t\2\2\u022b\u022c\7l\2\2\u022c\u022d"+
"\7o\2\2\u022d\u02bf\7r\2\2\u022e\u022f\7d\2\2\u022f\u0230\7x\2\2\u0230"+
"\u02bf\7e\2\2\u0231\u0232\7e\2\2\u0232\u0233\7n\2\2\u0233\u02bf\7k\2\2"+
"\u0234\u0235\7t\2\2\u0235\u0236\7v\2\2\u0236\u02bf\7u\2\2\u0237\u0238"+
"\7c\2\2\u0238\u0239\7f\2\2\u0239\u02bf\7e\2\2\u023a\u023b\7t\2\2\u023b"+
"\u023c\7t\2\2\u023c\u02bf\7c\2\2\u023d\u023e\7d\2\2\u023e\u023f\7x\2\2"+
"\u023f\u02bf\7u\2\2\u0240\u0241\7u\2\2\u0241\u0242\7g\2\2\u0242\u02bf"+
"\7k\2\2\u0243\u0244\7u\2\2\u0244\u0245\7c\2\2\u0245\u02bf\7z\2\2\u0246"+
"\u0247\7u\2\2\u0247\u0248\7v\2\2\u0248\u02bf\7{\2\2\u0249\u024a\7u\2\2"+
"\u024a\u024b\7v\2\2\u024b\u02bf\7c\2\2\u024c\u024d\7u\2\2\u024d\u024e"+
"\7v\2\2\u024e\u02bf\7z\2\2\u024f\u0250\7f\2\2\u0250\u0251\7g\2\2\u0251"+
"\u02bf\7{\2\2\u0252\u0253\7v\2\2\u0253\u0254\7z\2\2\u0254\u02bf\7c\2\2"+
"\u0255\u0256\7z\2\2\u0256\u0257\7c\2\2\u0257\u02bf\7c\2\2\u0258\u0259"+
"\7d\2\2\u0259\u025a\7e\2\2\u025a\u02bf\7e\2\2\u025b\u025c\7c\2\2\u025c"+
"\u025d\7j\2\2\u025d\u02bf\7z\2\2\u025e\u025f\7v\2\2\u025f\u0260\7{\2\2"+
"\u0260\u02bf\7c\2\2\u0261\u0262\7v\2\2\u0262\u0263\7z\2\2\u0263\u02bf"+
"\7u\2\2\u0264\u0265\7v\2\2\u0265\u0266\7c\2\2\u0266\u02bf\7u\2\2\u0267"+
"\u0268\7u\2\2\u0268\u0269\7j\2\2\u0269\u02bf\7{\2\2\u026a\u026b\7u\2\2"+
"\u026b\u026c\7j\2\2\u026c\u02bf\7z\2\2\u026d\u026e\7n\2\2\u026e\u026f"+
"\7f\2\2\u026f\u02bf\7{\2\2\u0270\u0271\7n\2\2\u0271\u0272\7f\2\2\u0272"+
"\u02bf\7c\2\2\u0273\u0274\7n\2\2\u0274\u0275\7f\2\2\u0275\u02bf\7z\2\2"+
"\u0276\u0277\7n\2\2\u0277\u0278\7c\2\2\u0278\u02bf\7z\2\2\u0279\u027a"+
"\7v\2\2\u027a\u027b\7c\2\2\u027b\u02bf\7{\2\2\u027c\u027d\7v\2\2\u027d"+
"\u027e\7c\2\2\u027e\u02bf\7z\2\2\u027f\u0280\7d\2\2\u0280\u0281\7e\2\2"+
"\u0281\u02bf\7u\2\2\u0282\u0283\7e\2\2\u0283\u0284\7n\2\2\u0284\u02bf"+
"\7x\2\2\u0285\u0286\7v\2\2\u0286\u0287\7u\2\2\u0287\u02bf\7z\2\2\u0288"+
"\u0289\7n\2\2\u0289\u028a\7c\2\2\u028a\u02bf\7u\2\2\u028b\u028c\7e\2\2"+
"\u028c\u028d\7r\2\2\u028d\u02bf\7{\2\2\u028e\u028f\7e\2\2\u028f\u0290"+
"\7o\2\2\u0290\u02bf\7r\2\2\u0291\u0292\7e\2\2\u0292\u0293\7r\2\2\u0293"+
"\u02bf\7z\2\2\u0294\u0295\7f\2\2\u0295\u0296\7e\2\2\u0296\u02bf\7r\2\2"+
"\u0297\u0298\7f\2\2\u0298\u0299\7g\2\2\u0299\u02bf\7e\2\2\u029a\u029b"+
"\7k\2\2\u029b\u029c\7p\2\2\u029c\u02bf\7e\2\2\u029d\u029e\7c\2\2\u029e"+
"\u029f\7z\2\2\u029f\u02bf\7u\2\2\u02a0\u02a1\7d\2\2\u02a1\u02a2\7p\2\2"+
"\u02a2\u02bf\7g\2\2\u02a3\u02a4\7e\2\2\u02a4\u02a5\7n\2\2\u02a5\u02bf"+
"\7f\2\2\u02a6\u02a7\7u\2\2\u02a7\u02a8\7d\2\2\u02a8\u02bf\7e\2\2\u02a9"+
"\u02aa\7k\2\2\u02aa\u02ab\7u\2\2\u02ab\u02bf\7e\2\2\u02ac\u02ad\7k\2\2"+
"\u02ad\u02ae\7p\2\2\u02ae\u02bf\7z\2\2\u02af\u02b0\7d\2\2\u02b0\u02b1"+
"\7g\2\2\u02b1\u02bf\7s\2\2\u02b2\u02b3\7u\2\2\u02b3\u02b4\7g\2\2\u02b4"+
"\u02bf\7f\2\2\u02b5\u02b6\7f\2\2\u02b6\u02b7\7g\2\2\u02b7\u02bf\7z\2\2"+
"\u02b8\u02b9\7k\2\2\u02b9\u02ba\7p\2\2\u02ba\u02bf\7{\2\2\u02bb\u02bc"+
"\7t\2\2\u02bc\u02bd\7q\2\2\u02bd\u02bf\7t\2\2\u02be\u01e0\3\2\2\2\u02be"+
"\u01e3\3\2\2\2\u02be\u01e6\3\2\2\2\u02be\u01e9\3\2\2\2\u02be\u01ec\3\2"+
"\2\2\u02be\u01ef\3\2\2\2\u02be\u01f2\3\2\2\2\u02be\u01f5\3\2\2\2\u02be"+
"\u01f8\3\2\2\2\u02be\u01fb\3\2\2\2\u02be\u01fe\3\2\2\2\u02be\u0201\3\2"+
"\2\2\u02be\u0204\3\2\2\2\u02be\u0207\3\2\2\2\u02be\u020a\3\2\2\2\u02be"+
"\u020d\3\2\2\2\u02be\u0210\3\2\2\2\u02be\u0213\3\2\2\2\u02be\u0216\3\2"+
"\2\2\u02be\u0219\3\2\2\2\u02be\u021c\3\2\2\2\u02be\u021f\3\2\2\2\u02be"+
"\u0222\3\2\2\2\u02be\u0225\3\2\2\2\u02be\u0228\3\2\2\2\u02be\u022b\3\2"+
"\2\2\u02be\u022e\3\2\2\2\u02be\u0231\3\2\2\2\u02be\u0234\3\2\2\2\u02be"+
"\u0237\3\2\2\2\u02be\u023a\3\2\2\2\u02be\u023d\3\2\2\2\u02be\u0240\3\2"+
"\2\2\u02be\u0243\3\2\2\2\u02be\u0246\3\2\2\2\u02be\u0249\3\2\2\2\u02be"+
"\u024c\3\2\2\2\u02be\u024f\3\2\2\2\u02be\u0252\3\2\2\2\u02be\u0255\3\2"+
"\2\2\u02be\u0258\3\2\2\2\u02be\u025b\3\2\2\2\u02be\u025e\3\2\2\2\u02be"+
"\u0261\3\2\2\2\u02be\u0264\3\2\2\2\u02be\u0267\3\2\2\2\u02be\u026a\3\2"+
"\2\2\u02be\u026d\3\2\2\2\u02be\u0270\3\2\2\2\u02be\u0273\3\2\2\2\u02be"+
"\u0276\3\2\2\2\u02be\u0279\3\2\2\2\u02be\u027c\3\2\2\2\u02be\u027f\3\2"+
"\2\2\u02be\u0282\3\2\2\2\u02be\u0285\3\2\2\2\u02be\u0288\3\2\2\2\u02be"+
"\u028b\3\2\2\2\u02be\u028e\3\2\2\2\u02be\u0291\3\2\2\2\u02be\u0294\3\2"+
"\2\2\u02be\u0297\3\2\2\2\u02be\u029a\3\2\2\2\u02be\u029d\3\2\2\2\u02be"+
"\u02a0\3\2\2\2\u02be\u02a3\3\2\2\2\u02be\u02a6\3\2\2\2\u02be\u02a9\3\2"+
"\2\2\u02be\u02ac\3\2\2\2\u02be\u02af\3\2\2\2\u02be\u02b2\3\2\2\2\u02be"+
"\u02b5\3\2\2\2\u02be\u02b8\3\2\2\2\u02be\u02bb\3\2\2\2\u02bf\u0094\3\2"+
"\2\2\u02c0\u02c1\7}\2\2\u02c1\u02c2\7}\2\2\u02c2\u02c6\3\2\2\2\u02c3\u02c5"+
"\13\2\2\2\u02c4\u02c3\3\2\2\2\u02c5\u02c8\3\2\2\2\u02c6\u02c7\3\2\2\2"+
"\u02c6\u02c4\3\2\2\2\u02c7\u02c9\3\2\2\2\u02c8\u02c6\3\2\2\2\u02c9\u02ca"+
"\7\177\2\2\u02ca\u02cb\7\177\2\2\u02cb\u0096\3\2\2\2\u02cc\u02cd\7d\2"+
"\2\u02cd\u02ce\7{\2\2\u02ce\u02cf\7v\2\2\u02cf\u02e2\7g\2\2\u02d0\u02d1"+
"\7y\2\2\u02d1\u02d2\7q\2\2\u02d2\u02d3\7t\2\2\u02d3\u02e2\7f\2\2\u02d4"+
"\u02d5\7f\2\2\u02d5\u02d6\7y\2\2\u02d6\u02d7\7q\2\2\u02d7\u02d8\7t\2\2"+
"\u02d8\u02e2\7f\2\2\u02d9\u02da\7d\2\2\u02da\u02db\7q\2\2\u02db\u02dc"+
"\7q\2\2\u02dc\u02e2\7n\2\2\u02dd\u02de\7x\2\2\u02de\u02df\7q\2\2\u02df"+
"\u02e0\7k\2\2\u02e0\u02e2\7f\2\2\u02e1\u02cc\3\2\2\2\u02e1\u02d0\3\2\2"+
"\2\u02e1\u02d4\3\2\2\2\u02e1\u02d9\3\2\2\2\u02e1\u02dd\3\2\2\2\u02e2\u0098"+
"\3\2\2\2\u02e3\u02e9\7$\2\2\u02e4\u02e5\7^\2\2\u02e5\u02e8\7$\2\2\u02e6"+
"\u02e8\n\2\2\2\u02e7\u02e4\3\2\2\2\u02e7\u02e6\3\2\2\2\u02e8\u02eb\3\2"+
"\2\2\u02e9\u02e7\3\2\2\2\u02e9\u02ea\3\2\2\2\u02ea\u02ec\3\2\2\2\u02eb"+
"\u02e9\3\2\2\2\u02ec\u02ed\7$\2\2\u02ed\u009a\3\2\2\2\u02ee\u02f2\7)\2"+
"\2\u02ef\u02f0\7^\2\2\u02f0\u02f3\7)\2\2\u02f1\u02f3\n\3\2\2\u02f2\u02ef"+
"\3\2\2\2\u02f2\u02f1\3\2\2\2\u02f3\u02f4\3\2\2\2\u02f4\u02f5\7)\2\2\u02f5"+
"\u009c\3\2\2\2\u02f6\u02f7\7v\2\2\u02f7\u02f8\7t\2\2\u02f8\u02f9\7w\2"+
"\2\u02f9\u0300\7g\2\2\u02fa\u02fb\7h\2\2\u02fb\u02fc\7c\2\2\u02fc\u02fd"+
"\7n\2\2\u02fd\u02fe\7u\2\2\u02fe\u0300\7g\2\2\u02ff\u02f6\3\2\2\2\u02ff"+
"\u02fa\3\2\2\2\u0300\u009e\3\2\2\2\u0301\u0304\5\u00a1Q\2\u0302\u0304"+
"\5\u00a9U\2\u0303\u0301\3\2\2\2\u0303\u0302\3\2\2\2\u0304\u00a0\3\2\2"+
"\2\u0305\u0309\5\u00a3R\2\u0306\u0309\5\u00a5S\2\u0307\u0309\5\u00a7T"+
"\2\u0308\u0305\3\2\2\2\u0308\u0306\3\2\2\2\u0308\u0307\3\2\2\2\u0309\u00a2"+
"\3\2\2\2\u030a\u0310\7\'\2\2\u030b\u030c\7\62\2\2\u030c\u0310\7d\2\2\u030d"+
"\u030e\7\62\2\2\u030e\u0310\7D\2\2\u030f\u030a\3\2\2\2\u030f\u030b\3\2"+
"\2\2\u030f\u030d\3\2\2\2\u0310\u0314\3\2\2\2\u0311\u0313\5\u00b1Y\2\u0312"+
"\u0311\3\2\2\2\u0313\u0316\3\2\2\2\u0314\u0312\3\2\2\2\u0314\u0315\3\2"+
"\2\2\u0315\u0317\3\2\2\2\u0316\u0314\3\2\2\2\u0317\u0319\7\60\2\2\u0318"+
"\u031a\5\u00b1Y\2\u0319\u0318\3\2\2\2\u031a\u031b\3\2\2\2\u031b\u0319"+
"\3\2\2\2\u031b\u031c\3\2\2\2\u031c\u00a4\3\2\2\2\u031d\u031f\5\u00b3Z"+
"\2\u031e\u031d\3\2\2\2\u031f\u0322\3\2\2\2\u0320\u031e\3\2\2\2\u0320\u0321"+
"\3\2\2\2\u0321\u0323\3\2\2\2\u0322\u0320\3\2\2\2\u0323\u0325\7\60\2\2"+
"\u0324\u0326\5\u00b3Z\2\u0325\u0324\3\2\2\2\u0326\u0327\3\2\2\2\u0327"+
"\u0325\3\2\2\2\u0327\u0328\3\2\2\2\u0328\u00a6\3\2\2\2\u0329\u032f\7&"+
"\2\2\u032a\u032b\7\62\2\2\u032b\u032f\7z\2\2\u032c\u032d\7\62\2\2\u032d"+
"\u032f\7Z\2\2\u032e\u0329\3\2\2\2\u032e\u032a\3\2\2\2\u032e\u032c\3\2"+
"\2\2\u032f\u0333\3\2\2\2\u0330\u0332\5\u00b5[\2\u0331\u0330\3\2\2\2\u0332"+
"\u0335\3\2\2\2\u0333\u0331\3\2\2\2\u0333\u0334\3\2\2\2\u0334\u0336\3\2"+
"\2\2\u0335\u0333\3\2\2\2\u0336\u0338\7\60\2\2\u0337\u0339\5\u00b5[\2\u0338"+
"\u0337\3\2\2\2\u0339\u033a\3\2\2\2\u033a\u0338\3\2\2\2\u033a\u033b\3\2"+
"\2\2\u033b\u00a8\3\2\2\2\u033c\u0340\5\u00adW\2\u033d\u0340\5\u00afX\2"+
"\u033e\u0340\5\u00abV\2\u033f\u033c\3\2\2\2\u033f\u033d\3\2\2\2\u033f"+
"\u033e\3\2\2\2\u0340\u00aa\3\2\2\2\u0341\u0342\7\62\2\2\u0342\u0344\t"+
"\4\2\2\u0343\u0345\5\u00b1Y\2\u0344\u0343\3\2\2\2\u0345\u0346\3\2\2\2"+
"\u0346\u0344\3\2\2\2\u0346\u0347\3\2\2\2\u0347\u034f\3\2\2\2\u0348\u034a"+
"\7\'\2\2\u0349\u034b\5\u00b1Y\2\u034a\u0349\3\2\2\2\u034b\u034c\3\2\2"+
"\2\u034c\u034a\3\2\2\2\u034c\u034d\3\2\2\2\u034d\u034f\3\2\2\2\u034e\u0341"+
"\3\2\2\2\u034e\u0348\3\2\2\2\u034f\u00ac\3\2\2\2\u0350\u0352\5\u00b3Z"+
"\2\u0351\u0350\3\2\2\2\u0352\u0353\3\2\2\2\u0353\u0351\3\2\2\2\u0353\u0354"+
"\3\2\2\2\u0354\u00ae\3\2\2\2\u0355\u035b\7&\2\2\u0356\u0357\7\62\2\2\u0357"+
"\u035b\7z\2\2\u0358\u0359\7\62\2\2\u0359\u035b\7Z\2\2\u035a\u0355\3\2"+
"\2\2\u035a\u0356\3\2\2\2\u035a\u0358\3\2\2\2\u035b\u035d\3\2\2\2\u035c"+
"\u035e\5\u00b5[\2\u035d\u035c\3\2\2\2\u035e\u035f\3\2\2\2\u035f\u035d"+
"\3\2\2\2\u035f\u0360\3\2\2\2\u0360\u00b0\3\2\2\2\u0361\u0362\t\5\2\2\u0362"+
"\u00b2\3\2\2\2\u0363\u0364\t\6\2\2\u0364\u00b4\3\2\2\2\u0365\u0366\t\7"+
"\2\2\u0366\u00b6\3\2\2\2\u0367\u036b\5\u00b9]\2\u0368\u036a\5\u00bb^\2"+
"\u0369\u0368\3\2\2\2\u036a\u036d\3\2\2\2\u036b\u0369\3\2\2\2\u036b\u036c"+
"\3\2\2\2\u036c\u00b8\3\2\2\2\u036d\u036b\3\2\2\2\u036e\u036f\t\b\2\2\u036f"+
"\u00ba\3\2\2\2\u0370\u0371\t\t\2\2\u0371\u00bc\3\2\2\2\u0372\u0376\7#"+
"\2\2\u0373\u0375\5\u00bb^\2\u0374\u0373\3\2\2\2\u0375\u0378\3\2\2\2\u0376"+
"\u0374\3\2\2\2\u0376\u0377\3\2\2\2\u0377\u037a\3\2\2\2\u0378\u0376\3\2"+
"\2\2\u0379\u037b\t\n\2\2\u037a\u0379\3\2\2\2\u037b\u037c\3\2\2\2\u037c"+
"\u037a\3\2\2\2\u037c\u037d\3\2\2\2\u037d\u00be\3\2\2\2\u037e\u0380\t\13"+
"\2\2\u037f\u037e\3\2\2\2\u0380\u0381\3\2\2\2\u0381\u037f\3\2\2\2\u0381"+
"\u0382\3\2\2\2\u0382\u0383\3\2\2\2\u0383\u0384\b`\2\2\u0384\u00c0\3\2"+
"\2\2\u0385\u0386\7\61\2\2\u0386\u0387\7\61\2\2\u0387\u038b\3\2\2\2\u0388"+
"\u038a\n\f\2\2\u0389\u0388\3\2\2\2\u038a\u038d\3\2\2\2\u038b\u0389\3\2"+
"\2\2\u038b\u038c\3\2\2\2\u038c\u038e\3\2\2\2\u038d\u038b\3\2\2\2\u038e"+
"\u038f\ba\3\2\u038f\u00c2\3\2\2\2\u0390\u0391\7\61\2\2\u0391\u0392\7,"+
"\2\2\u0392\u0396\3\2\2\2\u0393\u0395\13\2\2\2\u0394\u0393\3\2\2\2\u0395"+
"\u0398\3\2\2\2\u0396\u0397\3\2\2\2\u0396\u0394\3\2\2\2\u0397\u0399\3\2"+
"\2\2\u0398\u0396\3\2\2\2\u0399\u039a\7,\2\2\u039a\u039b\7\61\2\2\u039b"+
"\u039c\3\2\2\2\u039c\u039d\bb\3\2\u039d\u00c4\3\2\2\2!\2\u02be\u02c6\u02e1"+
"\u02e7\u02e9\u02f2\u02ff\u0303\u0308\u030f\u0314\u031b\u0320\u0327\u032e"+
"\u0333\u033a\u033f\u0346\u034c\u034e\u0353\u035a\u035f\u036b\u0376\u037c"+
"\u0381\u038b\u0396\4\2\3\2\2\4\2";
public static final ATN _ATN =
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
static {

View File

@ -69,26 +69,27 @@ T__67=68
T__68=69
T__69=70
T__70=71
MNEMONIC=72
KICKASM=73
SIMPLETYPE=74
STRING=75
CHAR=76
BOOLEAN=77
NUMBER=78
NUMFLOAT=79
BINFLOAT=80
DECFLOAT=81
HEXFLOAT=82
NUMINT=83
BININTEGER=84
DECINTEGER=85
HEXINTEGER=86
NAME=87
ASMREL=88
WS=89
COMMENT_LINE=90
COMMENT_BLOCK=91
T__71=72
MNEMONIC=73
KICKASM=74
SIMPLETYPE=75
STRING=76
CHAR=77
BOOLEAN=78
NUMBER=79
NUMFLOAT=80
BINFLOAT=81
DECFLOAT=82
HEXFLOAT=83
NUMINT=84
BININTEGER=85
DECINTEGER=86
HEXINTEGER=87
NAME=88
ASMREL=89
WS=90
COMMENT_LINE=91
COMMENT_BLOCK=92
'import'=1
'='=2
';'=3
@ -140,23 +141,24 @@ COMMENT_BLOCK=91
'|'=49
'&&'=50
'||'=51
'+='=52
'-='=53
'*='=54
'/='=55
'%='=56
'<<='=57
'>>='=58
'&='=59
'|='=60
'^='=61
'kickasm'=62
'resource'=63
'uses'=64
'clobbers'=65
'bytes'=66
'cycles'=67
'pc'=68
'.byte'=69
'#'=70
'.'=71
'?'=52
'+='=53
'-='=54
'*='=55
'/='=56
'%='=57
'<<='=58
'>>='=59
'&='=60
'|='=61
'^='=62
'kickasm'=63
'resource'=64
'uses'=65
'clobbers'=66
'bytes'=67
'cycles'=68
'pc'=69
'.byte'=70
'#'=71
'.'=72

View File

@ -633,6 +633,18 @@ public interface KickCListener extends ParseTreeListener {
* @param ctx the parse tree
*/
void exitExprId(KickCParser.ExprIdContext ctx);
/**
* Enter a parse tree produced by the {@code exprTernary}
* labeled alternative in {@link KickCParser#expr}.
* @param ctx the parse tree
*/
void enterExprTernary(KickCParser.ExprTernaryContext ctx);
/**
* Exit a parse tree produced by the {@code exprTernary}
* labeled alternative in {@link KickCParser#expr}.
* @param ctx the parse tree
*/
void exitExprTernary(KickCParser.ExprTernaryContext ctx);
/**
* Enter a parse tree produced by the {@code exprAssignment}
* labeled alternative in {@link KickCParser#expr}.

File diff suppressed because it is too large Load Diff

View File

@ -377,6 +377,13 @@ public interface KickCVisitor<T> extends ParseTreeVisitor<T> {
* @return the visitor result
*/
T visitExprId(KickCParser.ExprIdContext ctx);
/**
* Visit a parse tree produced by the {@code exprTernary}
* labeled alternative in {@link KickCParser#expr}.
* @param ctx the parse tree
* @return the visitor result
*/
T visitExprTernary(KickCParser.ExprTernaryContext ctx);
/**
* Visit a parse tree produced by the {@code exprAssignment}
* labeled alternative in {@link KickCParser#expr}.

View File

@ -594,10 +594,8 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
public Void visitStmtIfElse(KickCParser.StmtIfElseContext ctx) {
KickCParser.StmtContext ifStmt = ctx.stmt(0);
KickCParser.StmtContext elseStmt = ctx.stmt(1);
PrePostModifierHandler.addPreModifiers(this, ctx.expr());
RValue rValue = (RValue) this.visit(ctx.expr());
List<Comment> comments = ensureUnusedComments(getCommentsSymbol(ctx));
if(elseStmt == null) {
@ -1216,6 +1214,33 @@ public class Pass0GenerateStatementSequence extends KickCBaseVisitor<Object> {
return tmpVarRef;
}
@Override
public RValue visitExprTernary(KickCParser.ExprTernaryContext ctx) {
RValue condValue = (RValue) this.visit(ctx.expr(0));
Label trueLabel = getCurrentScope().addLabelIntermediate();
Label falseLabel = getCurrentScope().addLabelIntermediate();
Label endJumpLabel = getCurrentScope().addLabelIntermediate();
sequence.addStatement(new StatementConditionalJump(condValue, trueLabel.getRef(), new StatementSource(ctx), Comment.NO_COMMENTS));
sequence.addStatement(new StatementLabel(falseLabel.getRef(), new StatementSource(ctx), Comment.NO_COMMENTS));
RValue falseValue = (RValue) this.visit(ctx.expr(2));
VariableRef falseVar = getCurrentScope().addVariableIntermediate().getRef();
sequence.addStatement(new StatementAssignment(falseVar, null, null, falseValue, new StatementSource(ctx), Comment.NO_COMMENTS));
sequence.addStatement(new StatementJump(endJumpLabel.getRef(), new StatementSource(ctx), Comment.NO_COMMENTS));
sequence.addStatement(new StatementLabel(trueLabel.getRef(), new StatementSource(ctx), Comment.NO_COMMENTS));
RValue trueValue = (RValue) this.visit(ctx.expr(1));
VariableRef trueVar = getCurrentScope().addVariableIntermediate().getRef();
sequence.addStatement(new StatementAssignment(trueVar, null, null, trueValue, new StatementSource(ctx), Comment.NO_COMMENTS));
sequence.addStatement(new StatementLabel(endJumpLabel.getRef(), new StatementSource(ctx), Comment.NO_COMMENTS));
StatementPhiBlock phiBlock = new StatementPhiBlock(Comment.NO_COMMENTS);
phiBlock.setSource(new StatementSource(ctx));
VariableRef finalVar = getCurrentScope().addVariableIntermediate().getRef();
StatementPhiBlock.PhiVariable phiVariable = phiBlock.addPhiVariable(finalVar);
phiVariable.setrValue(trueLabel.getRef(), trueVar);
phiVariable.setrValue(falseLabel.getRef(), falseVar);
sequence.addStatement(phiBlock);
return finalVar;
}
@Override
public Object visitExprPreMod(KickCParser.ExprPreModContext ctx) {
RValue child = (RValue) this.visit(ctx.expr());

View File

@ -1,14 +1,22 @@
package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.*;
import dk.camelot64.kickc.model.values.LabelRef;
import dk.camelot64.kickc.model.values.SymbolRef;
import dk.camelot64.kickc.model.values.VariableRef;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.VariableReferenceInfos;
import dk.camelot64.kickc.model.iterator.ProgramValue;
import dk.camelot64.kickc.model.iterator.ProgramValueIterator;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementCall;
import dk.camelot64.kickc.model.statements.StatementConditionalJump;
import dk.camelot64.kickc.model.statements.StatementPhiBlock;
import dk.camelot64.kickc.model.symbols.Procedure;
import dk.camelot64.kickc.model.values.LabelRef;
import dk.camelot64.kickc.model.values.SymbolRef;
import dk.camelot64.kickc.model.values.SymbolVariableRef;
import dk.camelot64.kickc.model.values.VariableRef;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
@ -29,7 +37,7 @@ public class Pass1AssertUsedVars extends Pass1Base {
VariableReferenceInfos referenceInfos = getProgram().getVariableReferenceInfos();
ControlFlowBlock beginBlock = getProgram().getGraph().getBlock(new LabelRef(SymbolRef.BEGIN_BLOCK_NAME));
assertUsedVars(beginBlock, referenceInfos, new LinkedHashSet<>(), new LinkedHashSet<>());
assertUsedVars(beginBlock, null, referenceInfos, new LinkedHashSet<>(), new LinkedHashSet<>());
getProgram().setVariableReferenceInfos(null);
new PassNStatementIndices(getProgram()).clearStatementIndices();
@ -42,16 +50,23 @@ public class Pass1AssertUsedVars extends Pass1Base {
* Follow the control flow of the graph recursively.
*
* @param block The block to examine
* @param predecessor The block jumping into this block (used for phi analysis)
* @param referenceInfos Information about assigned/used variables in statements
* @param defined Variables already assigned a value at the point of the first execution of the block
* @param visited Blocks already visited
*/
public void assertUsedVars(ControlFlowBlock block, VariableReferenceInfos referenceInfos, Collection<VariableRef> defined, Collection<LabelRef> visited) {
public void assertUsedVars(ControlFlowBlock block, LabelRef predecessor, VariableReferenceInfos referenceInfos, Collection<VariableRef> defined, Collection<LabelRef> visited) {
// If the block has a phi statement it is always examined (to not skip any of the predecessor checks)
assertUsedVarsPhi(block, predecessor, referenceInfos, defined);
// If we have already visited the block - skip it
if(visited.contains(block.getLabel())) {
return;
}
visited.add(block.getLabel());
// Examine all statements (except the potential PHI)
for(Statement statement : block.getStatements()) {
// PHI block has already been examined
if(statement instanceof StatementPhiBlock) continue;
Collection<VariableRef> used = referenceInfos.getUsedVars(statement);
for(VariableRef usedRef : used) {
if(!defined.contains(usedRef)) {
@ -70,16 +85,57 @@ public class Pass1AssertUsedVars extends Pass1Base {
}
ControlFlowBlock procedureStart = getProgram().getGraph().getBlock(call.getProcedure().getLabelRef());
assertUsedVars(procedureStart, referenceInfos, defined, visited);
assertUsedVars(procedureStart, block.getLabel(), referenceInfos, defined, visited);
} else if(statement instanceof StatementConditionalJump) {
StatementConditionalJump cond = (StatementConditionalJump) statement;
ControlFlowBlock jumpTo = getProgram().getGraph().getBlock(cond.getDestination());
assertUsedVars(jumpTo, referenceInfos, defined, visited);
assertUsedVars(jumpTo, block.getLabel(), referenceInfos, defined, visited);
}
}
ControlFlowBlock successor = getProgram().getGraph().getBlock(block.getDefaultSuccessor());
if(successor != null) {
assertUsedVars(successor, referenceInfos, defined, visited);
assertUsedVars(successor, block.getLabel(), referenceInfos, defined, visited);
}
}
/**
* Assert that all used vars have been assigned values before the use - in a PHI block.
*
* @param block The block to examine
* @param predecessor The block jumping into this block (used for phi analysis)
* @param referenceInfos Information about assigned/used variables in statements
* @param defined Variables already assigned a value at the point of the first execution of the block
* @param visited Blocks already visited
*/
private void assertUsedVarsPhi(ControlFlowBlock block, LabelRef predecessor, VariableReferenceInfos referenceInfos, Collection<VariableRef> defined) {
if(predecessor != null && block.hasPhiBlock()) {
StatementPhiBlock phiBlock = block.getPhiBlock();
ArrayList<SymbolVariableRef> used = new ArrayList<>();
for(StatementPhiBlock.PhiVariable phiVariable : phiBlock.getPhiVariables()) {
int i = 0;
for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) {
if(predecessor.equals(phiRValue.getPredecessor())) {
ProgramValueIterator.execute(new ProgramValue.PhiValue(phiVariable, i), (programValue, currentStmt, stmtIt, currentBlock) -> {
if(programValue.get() instanceof SymbolVariableRef) {
if(!used.contains(programValue.get())) used.add((SymbolVariableRef) programValue.get());
}
}, phiBlock, null, block);
}
i++;
}
}
// Found used variables - check that they are defined
for(SymbolVariableRef usedRef : used) {
if(!defined.contains(usedRef)) {
throw new CompileError("Error! Variable used before being defined " + usedRef.toString(getProgram()) + " in " + phiBlock.toString(getProgram(), false), phiBlock.getSource());
}
}
// Add all variables fefined by the PHI block
Collection<VariableRef> defd = referenceInfos.getDefinedVars(phiBlock);
for(VariableRef definedRef : defd) {
defined.add(definedRef);
}
}
}

View File

@ -3,10 +3,7 @@ package dk.camelot64.kickc.passes;
import dk.camelot64.kickc.model.CompileError;
import dk.camelot64.kickc.model.ControlFlowBlock;
import dk.camelot64.kickc.model.Program;
import dk.camelot64.kickc.model.statements.Statement;
import dk.camelot64.kickc.model.statements.StatementAssignment;
import dk.camelot64.kickc.model.statements.StatementCall;
import dk.camelot64.kickc.model.statements.StatementCallPointer;
import dk.camelot64.kickc.model.statements.*;
import dk.camelot64.kickc.model.symbols.Procedure;
import dk.camelot64.kickc.model.symbols.Scope;
import dk.camelot64.kickc.model.types.SymbolTypeInference;
@ -32,6 +29,14 @@ public class Pass1TypeInference extends Pass1Base {
} catch(CompileError e) {
throw new CompileError(e.getMessage(), statement.getSource());
}
} else if(statement instanceof StatementPhiBlock) {
for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) {
try {
SymbolTypeInference.inferPhiVariable(getProgram(), phiVariable, false);
} catch(CompileError e) {
throw new CompileError(e.getMessage(), statement.getSource());
}
}
} else if(statement instanceof StatementCall) {
StatementCall call = (StatementCall) statement;
String procedureName = call.getProcedureName();

View File

@ -32,6 +32,16 @@ public class TestPrograms {
public TestPrograms() {
}
@Test
public void testTernary2() throws IOException, URISyntaxException {
compileAndCompare("ternary-2");
}
@Test
public void testTernary1() throws IOException, URISyntaxException {
compileAndCompare("ternary-1");
}
@Test
public void testPointerPointer3() throws IOException, URISyntaxException {
compileAndCompare("pointer-pointer-3");

8
src/test/kc/ternary-1.kc Normal file
View File

@ -0,0 +1,8 @@
// Tests the ternary operator
void main() {
const byte* SCREEN = $400;
for( byte i: 0..9) {
SCREEN[i] = i<5?'a':'b';
}
}

7
src/test/kc/ternary-2.kc Normal file
View File

@ -0,0 +1,7 @@
// Tests the ternary operator - when the condition is constant
void main() {
const byte* SCREEN = $400;
SCREEN[0] = true?'a':'b';
SCREEN[1] = false?'a':'b';
}

View File

@ -0,0 +1,21 @@
// Tests the ternary operator
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
main: {
.label SCREEN = $400
ldx #0
b1:
cpx #5
bcc b2
lda #'b'
jmp b3
b2:
lda #'a'
b3:
sta SCREEN,x
inx
cpx #$a
bne b1
rts
}

View File

@ -0,0 +1,28 @@
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
main: scope:[main] from @1
[4] phi()
to:main::@1
main::@1: scope:[main] from main main::@3
[5] (byte) main::i#2 ← phi( main/(byte/signed byte/word/signed word/dword/signed dword) 0 main::@3/(byte) main::i#1 )
[6] if((byte) main::i#2<(byte/signed byte/word/signed word/dword/signed dword) 5) goto main::@3
to:main::@2
main::@2: scope:[main] from main::@1
[7] phi()
to:main::@3
main::@3: scope:[main] from main::@1 main::@2
[8] (byte~) main::$3 ← phi( main::@1/(byte) 'a' main::@2/(byte) 'b' )
[9] *((const byte*) main::SCREEN#0 + (byte) main::i#2) ← (byte~) main::$3
[10] (byte) main::i#1 ← ++ (byte) main::i#2
[11] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) $a) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@3
[12] return
to:@return

427
src/test/ref/ternary-1.log Normal file
View File

@ -0,0 +1,427 @@
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
to:@1
main: scope:[main] from @1
(byte*) main::SCREEN#0 ← ((byte*)) (word/signed word/dword/signed dword) $400
(byte) main::i#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0
to:main::@1
main::@1: scope:[main] from main main::@4
(byte) main::i#2 ← phi( main/(byte) main::i#0 main::@4/(byte) main::i#1 )
(bool~) main::$0 ← (byte) main::i#2 < (byte/signed byte/word/signed word/dword/signed dword) 5
if((bool~) main::$0) goto main::@2
to:main::@3
main::@2: scope:[main] from main::@1
(byte) main::i#4 ← phi( main::@1/(byte) main::i#2 )
(byte~) main::$2 ← (byte) 'a'
to:main::@4
main::@3: scope:[main] from main::@1
(byte) main::i#5 ← phi( main::@1/(byte) main::i#2 )
(byte~) main::$1 ← (byte) 'b'
to:main::@4
main::@4: scope:[main] from main::@2 main::@3
(byte) main::i#3 ← phi( main::@2/(byte) main::i#4 main::@3/(byte) main::i#5 )
(byte~) main::$3 ← phi( main::@2/(byte~) main::$2 main::@3/(byte~) main::$1 )
*((byte*) main::SCREEN#0 + (byte) main::i#3) ← (byte~) main::$3
(byte) main::i#1 ← (byte) main::i#3 + rangenext(0,9)
(bool~) main::$4 ← (byte) main::i#1 != rangelast(0,9)
if((bool~) main::$4) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@4
return
to:@return
@1: scope:[] from @begin
call main
to:@2
@2: scope:[] from @1
to:@end
@end: scope:[] from @2
SYMBOL TABLE SSA
(label) @1
(label) @2
(label) @begin
(label) @end
(void()) main()
(bool~) main::$0
(byte~) main::$1
(byte~) main::$2
(byte~) main::$3
(bool~) main::$4
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@4
(label) main::@return
(byte*) main::SCREEN
(byte*) main::SCREEN#0
(byte) main::i
(byte) main::i#0
(byte) main::i#1
(byte) main::i#2
(byte) main::i#3
(byte) main::i#4
(byte) main::i#5
Culled Empty Block (label) @2
Successful SSA optimization Pass2CullEmptyBlocks
Alias (byte) main::i#2 = (byte) main::i#4 (byte) main::i#5
Successful SSA optimization Pass2AliasElimination
Alias (byte) main::i#2 = (byte) main::i#3
Successful SSA optimization Pass2AliasElimination
Simple Condition (bool~) main::$0 [4] if((byte) main::i#2<(byte/signed byte/word/signed word/dword/signed dword) 5) goto main::@2
Simple Condition (bool~) main::$4 [13] if((byte) main::i#1!=rangelast(0,9)) goto main::@1
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant (const byte*) main::SCREEN#0 = ((byte*))$400
Constant (const byte) main::i#0 = 0
Constant (const byte) main::$2 = 'a'
Constant (const byte) main::$1 = 'b'
Successful SSA optimization Pass2ConstantIdentification
Resolved ranged next value main::i#1 ← ++ main::i#2 to ++
Resolved ranged comparison value if(main::i#1!=rangelast(0,9)) goto main::@1 to (byte/signed byte/word/signed word/dword/signed dword) $a
Culled Empty Block (label) main::@2
Successful SSA optimization Pass2CullEmptyBlocks
Inlining constant with var siblings (const byte) main::i#0
Constant inlined main::$1 = (byte) 'b'
Constant inlined main::i#0 = (byte/signed byte/word/signed word/dword/signed dword) 0
Constant inlined main::$2 = (byte) 'a'
Successful SSA optimization Pass2ConstantInlining
Added new block during phi lifting main::@8(between main::@4 and main::@1)
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
Adding NOP phi() at start of main::@3
CALL GRAPH
Calls in [] to main:2
Created 2 initial phi equivalence classes
Coalesced [13] main::i#6 ← main::i#1
Coalesced down to 2 phi equivalence classes
Culled Empty Block (label) main::@8
Renumbering block main::@3 to main::@2
Renumbering block main::@4 to main::@3
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
Adding NOP phi() at start of main::@2
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
main: scope:[main] from @1
[4] phi()
to:main::@1
main::@1: scope:[main] from main main::@3
[5] (byte) main::i#2 ← phi( main/(byte/signed byte/word/signed word/dword/signed dword) 0 main::@3/(byte) main::i#1 )
[6] if((byte) main::i#2<(byte/signed byte/word/signed word/dword/signed dword) 5) goto main::@3
to:main::@2
main::@2: scope:[main] from main::@1
[7] phi()
to:main::@3
main::@3: scope:[main] from main::@1 main::@2
[8] (byte~) main::$3 ← phi( main::@1/(byte) 'a' main::@2/(byte) 'b' )
[9] *((const byte*) main::SCREEN#0 + (byte) main::i#2) ← (byte~) main::$3
[10] (byte) main::i#1 ← ++ (byte) main::i#2
[11] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) $a) goto main::@1
to:main::@return
main::@return: scope:[main] from main::@3
[12] return
to:@return
VARIABLE REGISTER WEIGHTS
(void()) main()
(byte~) main::$3 11.0
(byte*) main::SCREEN
(byte) main::i
(byte) main::i#1 16.5
(byte) main::i#2 8.8
Initial phi equivalence classes
[ main::i#2 main::i#1 ]
[ main::$3 ]
Complete equivalence classes
[ main::i#2 main::i#1 ]
[ main::$3 ]
Allocated zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
Allocated zp ZP_BYTE:3 [ main::$3 ]
INITIAL ASM
//SEG0 File Comments
// Tests the ternary operator
//SEG1 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
//SEG2 Global Constants & labels
//SEG3 @begin
bbegin:
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
//SEG5 @1
b1:
//SEG6 [2] call main
//SEG7 [4] phi from @1 to main [phi:@1->main]
main_from_b1:
jsr main
//SEG8 [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
//SEG9 @end
bend:
//SEG10 main
main: {
.label SCREEN = $400
.label _3 = 3
.label i = 2
//SEG11 [5] phi from main to main::@1 [phi:main->main::@1]
b1_from_main:
//SEG12 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
lda #0
sta i
jmp b1
//SEG13 [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1]
b1_from_b3:
//SEG14 [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@3->main::@1#0] -- register_copy
jmp b1
//SEG15 main::@1
b1:
//SEG16 [6] if((byte) main::i#2<(byte/signed byte/word/signed word/dword/signed dword) 5) goto main::@3 -- vbuz1_lt_vbuc1_then_la1
lda i
cmp #5
bcc b3_from_b1
//SEG17 [7] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
b2_from_b1:
jmp b2
//SEG18 main::@2
b2:
//SEG19 [8] phi from main::@2 to main::@3 [phi:main::@2->main::@3]
b3_from_b2:
//SEG20 [8] phi (byte~) main::$3 = (byte) 'b' [phi:main::@2->main::@3#0] -- vbuz1=vbuc1
lda #'b'
sta _3
jmp b3
//SEG21 [8] phi from main::@1 to main::@3 [phi:main::@1->main::@3]
b3_from_b1:
//SEG22 [8] phi (byte~) main::$3 = (byte) 'a' [phi:main::@1->main::@3#0] -- vbuz1=vbuc1
lda #'a'
sta _3
jmp b3
//SEG23 main::@3
b3:
//SEG24 [9] *((const byte*) main::SCREEN#0 + (byte) main::i#2) ← (byte~) main::$3 -- pbuc1_derefidx_vbuz1=vbuz2
lda _3
ldy i
sta SCREEN,y
//SEG25 [10] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
inc i
//SEG26 [11] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) $a) goto main::@1 -- vbuz1_neq_vbuc1_then_la1
lda #$a
cmp i
bne b1_from_b3
jmp breturn
//SEG27 main::@return
breturn:
//SEG28 [12] return
rts
}
REGISTER UPLIFT POTENTIAL REGISTERS
Potential registers zp ZP_BYTE:2 [ main::i#2 main::i#1 ] : zp ZP_BYTE:2 , reg byte a , reg byte x , reg byte y ,
Potential registers zp ZP_BYTE:3 [ main::$3 ] : zp ZP_BYTE:3 , reg byte a , reg byte x , reg byte y ,
REGISTER UPLIFT SCOPES
Uplift Scope [main] 25.3: zp ZP_BYTE:2 [ main::i#2 main::i#1 ] 11: zp ZP_BYTE:3 [ main::$3 ]
Uplift Scope []
Uplifting [main] best 418 combination reg byte x [ main::i#2 main::i#1 ] reg byte a [ main::$3 ]
Uplifting [] best 418 combination
ASSEMBLER BEFORE OPTIMIZATION
//SEG0 File Comments
// Tests the ternary operator
//SEG1 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
//SEG2 Global Constants & labels
//SEG3 @begin
bbegin:
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
//SEG5 @1
b1:
//SEG6 [2] call main
//SEG7 [4] phi from @1 to main [phi:@1->main]
main_from_b1:
jsr main
//SEG8 [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
//SEG9 @end
bend:
//SEG10 main
main: {
.label SCREEN = $400
//SEG11 [5] phi from main to main::@1 [phi:main->main::@1]
b1_from_main:
//SEG12 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
ldx #0
jmp b1
//SEG13 [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1]
b1_from_b3:
//SEG14 [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@3->main::@1#0] -- register_copy
jmp b1
//SEG15 main::@1
b1:
//SEG16 [6] if((byte) main::i#2<(byte/signed byte/word/signed word/dword/signed dword) 5) goto main::@3 -- vbuxx_lt_vbuc1_then_la1
cpx #5
bcc b3_from_b1
//SEG17 [7] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
b2_from_b1:
jmp b2
//SEG18 main::@2
b2:
//SEG19 [8] phi from main::@2 to main::@3 [phi:main::@2->main::@3]
b3_from_b2:
//SEG20 [8] phi (byte~) main::$3 = (byte) 'b' [phi:main::@2->main::@3#0] -- vbuaa=vbuc1
lda #'b'
jmp b3
//SEG21 [8] phi from main::@1 to main::@3 [phi:main::@1->main::@3]
b3_from_b1:
//SEG22 [8] phi (byte~) main::$3 = (byte) 'a' [phi:main::@1->main::@3#0] -- vbuaa=vbuc1
lda #'a'
jmp b3
//SEG23 main::@3
b3:
//SEG24 [9] *((const byte*) main::SCREEN#0 + (byte) main::i#2) ← (byte~) main::$3 -- pbuc1_derefidx_vbuxx=vbuaa
sta SCREEN,x
//SEG25 [10] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
inx
//SEG26 [11] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) $a) goto main::@1 -- vbuxx_neq_vbuc1_then_la1
cpx #$a
bne b1_from_b3
jmp breturn
//SEG27 main::@return
breturn:
//SEG28 [12] return
rts
}
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp b1
Removing instruction jmp bend
Removing instruction jmp b1
Removing instruction jmp b2
Removing instruction jmp b3
Removing instruction jmp breturn
Succesful ASM optimization Pass5NextJumpElimination
Replacing label b1_from_b3 with b1
Removing instruction b1_from_bbegin:
Removing instruction b1:
Removing instruction main_from_b1:
Removing instruction bend_from_b1:
Removing instruction b1_from_b3:
Removing instruction b2_from_b1:
Removing instruction b3_from_b2:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction bend:
Removing instruction b1_from_main:
Removing instruction b2:
Removing instruction breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Relabelling long label b3_from_b1 to b2
Succesful ASM optimization Pass5RelabelLongLabels
Removing instruction jmp b1
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction bbegin:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(void()) main()
(byte~) main::$3 reg byte a 11.0
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@return
(byte*) main::SCREEN
(const byte*) main::SCREEN#0 SCREEN = ((byte*))(word/signed word/dword/signed dword) $400
(byte) main::i
(byte) main::i#1 reg byte x 16.5
(byte) main::i#2 reg byte x 8.8
reg byte x [ main::i#2 main::i#1 ]
reg byte a [ main::$3 ]
FINAL ASSEMBLER
Score: 256
//SEG0 File Comments
// Tests the ternary operator
//SEG1 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
//SEG2 Global Constants & labels
//SEG3 @begin
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
//SEG5 @1
//SEG6 [2] call main
//SEG7 [4] phi from @1 to main [phi:@1->main]
//SEG8 [3] phi from @1 to @end [phi:@1->@end]
//SEG9 @end
//SEG10 main
main: {
.label SCREEN = $400
//SEG11 [5] phi from main to main::@1 [phi:main->main::@1]
//SEG12 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
ldx #0
//SEG13 [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1]
//SEG14 [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@3->main::@1#0] -- register_copy
//SEG15 main::@1
b1:
//SEG16 [6] if((byte) main::i#2<(byte/signed byte/word/signed word/dword/signed dword) 5) goto main::@3 -- vbuxx_lt_vbuc1_then_la1
cpx #5
bcc b2
//SEG17 [7] phi from main::@1 to main::@2 [phi:main::@1->main::@2]
//SEG18 main::@2
//SEG19 [8] phi from main::@2 to main::@3 [phi:main::@2->main::@3]
//SEG20 [8] phi (byte~) main::$3 = (byte) 'b' [phi:main::@2->main::@3#0] -- vbuaa=vbuc1
lda #'b'
jmp b3
//SEG21 [8] phi from main::@1 to main::@3 [phi:main::@1->main::@3]
b2:
//SEG22 [8] phi (byte~) main::$3 = (byte) 'a' [phi:main::@1->main::@3#0] -- vbuaa=vbuc1
lda #'a'
//SEG23 main::@3
b3:
//SEG24 [9] *((const byte*) main::SCREEN#0 + (byte) main::i#2) ← (byte~) main::$3 -- pbuc1_derefidx_vbuxx=vbuaa
sta SCREEN,x
//SEG25 [10] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
inx
//SEG26 [11] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) $a) goto main::@1 -- vbuxx_neq_vbuc1_then_la1
cpx #$a
bne b1
//SEG27 main::@return
//SEG28 [12] return
rts
}

View File

@ -0,0 +1,17 @@
(label) @1
(label) @begin
(label) @end
(void()) main()
(byte~) main::$3 reg byte a 11.0
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@return
(byte*) main::SCREEN
(const byte*) main::SCREEN#0 SCREEN = ((byte*))(word/signed word/dword/signed dword) $400
(byte) main::i
(byte) main::i#1 reg byte x 16.5
(byte) main::i#2 reg byte x 8.8
reg byte x [ main::i#2 main::i#1 ]
reg byte a [ main::$3 ]

View File

@ -0,0 +1,12 @@
// Tests the ternary operator - when the condition is constant
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
main: {
.label SCREEN = $400
lda #'a'
sta SCREEN
lda #'b'
sta SCREEN+1
rts
}

View File

@ -0,0 +1,21 @@
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
main: scope:[main] from @1
[4] phi()
to:main::@1
main::@1: scope:[main] from main
[5] *((const byte*) main::SCREEN#0) ← (byte) 'a'
to:main::@2
main::@2: scope:[main] from main::@1
[6] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte) 'b'
to:main::@return
main::@return: scope:[main] from main::@2
[7] return
to:@return

310
src/test/ref/ternary-2.log Normal file
View File

@ -0,0 +1,310 @@
CONTROL FLOW GRAPH SSA
@begin: scope:[] from
to:@1
main: scope:[main] from @1
(byte*) main::SCREEN#0 ← ((byte*)) (word/signed word/dword/signed dword) $400
if(true) goto main::@1
to:main::@2
main::@1: scope:[main] from main
(byte~) main::$1 ← (byte) 'a'
to:main::@3
main::@2: scope:[main] from main
(byte~) main::$0 ← (byte) 'b'
to:main::@3
main::@3: scope:[main] from main::@1 main::@2
(byte~) main::$2 ← phi( main::@1/(byte~) main::$1 main::@2/(byte~) main::$0 )
*((byte*) main::SCREEN#0 + (byte/signed byte/word/signed word/dword/signed dword) 0) ← (byte~) main::$2
if(false) goto main::@4
to:main::@5
main::@4: scope:[main] from main::@3
(byte~) main::$4 ← (byte) 'a'
to:main::@6
main::@5: scope:[main] from main::@3
(byte~) main::$3 ← (byte) 'b'
to:main::@6
main::@6: scope:[main] from main::@4 main::@5
(byte~) main::$5 ← phi( main::@4/(byte~) main::$4 main::@5/(byte~) main::$3 )
*((byte*) main::SCREEN#0 + (byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte~) main::$5
to:main::@return
main::@return: scope:[main] from main::@6
return
to:@return
@1: scope:[] from @begin
call main
to:@2
@2: scope:[] from @1
to:@end
@end: scope:[] from @2
SYMBOL TABLE SSA
(label) @1
(label) @2
(label) @begin
(label) @end
(void()) main()
(byte~) main::$0
(byte~) main::$1
(byte~) main::$2
(byte~) main::$3
(byte~) main::$4
(byte~) main::$5
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@4
(label) main::@5
(label) main::@6
(label) main::@return
(byte*) main::SCREEN
(byte*) main::SCREEN#0
Culled Empty Block (label) @2
Successful SSA optimization Pass2CullEmptyBlocks
Constant (const byte*) main::SCREEN#0 = ((byte*))$400
Constant (const byte) main::$1 = 'a'
Constant (const byte) main::$0 = 'b'
Constant (const byte) main::$4 = 'a'
Constant (const byte) main::$3 = 'b'
Successful SSA optimization Pass2ConstantIdentification
Consolidated array index constant in *(main::SCREEN#0+0)
Consolidated array index constant in *(main::SCREEN#0+1)
Successful SSA optimization Pass2ConstantAdditionElimination
if() condition always true - replacing block destination [0] if(true) goto main::@1
if() condition always false - eliminating [3] if(false) goto main::@4
Successful SSA optimization Pass2ConstantIfs
Removing PHI-reference to removed block (main::@2) in block main::@3
Removing unused block main::@2
Removing PHI-reference to removed block (main::@4) in block main::@6
Removing unused block main::@4
Successful SSA optimization Pass2EliminateUnusedBlocks
Culled Empty Block (label) main::@1
Culled Empty Block (label) main::@5
Successful SSA optimization Pass2CullEmptyBlocks
Redundant Phi (byte~) main::$2 (const byte) main::$1
Redundant Phi (byte~) main::$5 (const byte) main::$3
Successful SSA optimization Pass2RedundantPhiElimination
Successful SSA optimization PassNEliminateUnusedVars
Constant inlined main::$1 = (byte) 'a'
Constant inlined main::$3 = (byte) 'b'
Successful SSA optimization Pass2ConstantInlining
Simplifying constant plus zero main::SCREEN#0+0
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
CALL GRAPH
Calls in [] to main:2
Created 0 initial phi equivalence classes
Coalesced down to 0 phi equivalence classes
Renumbering block main::@3 to main::@1
Renumbering block main::@6 to main::@2
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
FINAL CONTROL FLOW GRAPH
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[1] phi()
[2] call main
to:@end
@end: scope:[] from @1
[3] phi()
main: scope:[main] from @1
[4] phi()
to:main::@1
main::@1: scope:[main] from main
[5] *((const byte*) main::SCREEN#0) ← (byte) 'a'
to:main::@2
main::@2: scope:[main] from main::@1
[6] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte) 'b'
to:main::@return
main::@return: scope:[main] from main::@2
[7] return
to:@return
VARIABLE REGISTER WEIGHTS
(void()) main()
(byte*) main::SCREEN
Initial phi equivalence classes
Complete equivalence classes
INITIAL ASM
//SEG0 File Comments
// Tests the ternary operator - when the condition is constant
//SEG1 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
//SEG2 Global Constants & labels
//SEG3 @begin
bbegin:
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
//SEG5 @1
b1:
//SEG6 [2] call main
//SEG7 [4] phi from @1 to main [phi:@1->main]
main_from_b1:
jsr main
//SEG8 [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
//SEG9 @end
bend:
//SEG10 main
main: {
.label SCREEN = $400
jmp b1
//SEG11 main::@1
b1:
//SEG12 [5] *((const byte*) main::SCREEN#0) ← (byte) 'a' -- _deref_pbuc1=vbuc2
lda #'a'
sta SCREEN
jmp b2
//SEG13 main::@2
b2:
//SEG14 [6] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte) 'b' -- _deref_pbuc1=vbuc2
lda #'b'
sta SCREEN+1
jmp breturn
//SEG15 main::@return
breturn:
//SEG16 [7] return
rts
}
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [5] *((const byte*) main::SCREEN#0) ← (byte) 'a' [ ] ( main:2 [ ] ) always clobbers reg byte a
Statement [6] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte) 'b' [ ] ( main:2 [ ] ) always clobbers reg byte a
REGISTER UPLIFT SCOPES
Uplift Scope [main]
Uplift Scope []
Uplifting [main] best 66 combination
Uplifting [] best 66 combination
ASSEMBLER BEFORE OPTIMIZATION
//SEG0 File Comments
// Tests the ternary operator - when the condition is constant
//SEG1 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(bbegin)
.pc = $80d "Program"
//SEG2 Global Constants & labels
//SEG3 @begin
bbegin:
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
b1_from_bbegin:
jmp b1
//SEG5 @1
b1:
//SEG6 [2] call main
//SEG7 [4] phi from @1 to main [phi:@1->main]
main_from_b1:
jsr main
//SEG8 [3] phi from @1 to @end [phi:@1->@end]
bend_from_b1:
jmp bend
//SEG9 @end
bend:
//SEG10 main
main: {
.label SCREEN = $400
jmp b1
//SEG11 main::@1
b1:
//SEG12 [5] *((const byte*) main::SCREEN#0) ← (byte) 'a' -- _deref_pbuc1=vbuc2
lda #'a'
sta SCREEN
jmp b2
//SEG13 main::@2
b2:
//SEG14 [6] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte) 'b' -- _deref_pbuc1=vbuc2
lda #'b'
sta SCREEN+1
jmp breturn
//SEG15 main::@return
breturn:
//SEG16 [7] return
rts
}
ASSEMBLER OPTIMIZATIONS
Removing instruction jmp b1
Removing instruction jmp bend
Removing instruction jmp b1
Removing instruction jmp b2
Removing instruction jmp breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction b1_from_bbegin:
Removing instruction b1:
Removing instruction main_from_b1:
Removing instruction bend_from_b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction bend:
Removing instruction b1:
Removing instruction b2:
Removing instruction breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction bbegin:
Succesful ASM optimization Pass5UnusedLabelElimination
FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@return
(byte*) main::SCREEN
(const byte*) main::SCREEN#0 SCREEN = ((byte*))(word/signed word/dword/signed dword) $400
FINAL ASSEMBLER
Score: 18
//SEG0 File Comments
// Tests the ternary operator - when the condition is constant
//SEG1 Basic Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
//SEG2 Global Constants & labels
//SEG3 @begin
//SEG4 [1] phi from @begin to @1 [phi:@begin->@1]
//SEG5 @1
//SEG6 [2] call main
//SEG7 [4] phi from @1 to main [phi:@1->main]
//SEG8 [3] phi from @1 to @end [phi:@1->@end]
//SEG9 @end
//SEG10 main
main: {
.label SCREEN = $400
//SEG11 main::@1
//SEG12 [5] *((const byte*) main::SCREEN#0) ← (byte) 'a' -- _deref_pbuc1=vbuc2
lda #'a'
sta SCREEN
//SEG13 main::@2
//SEG14 [6] *((const byte*) main::SCREEN#0+(byte/signed byte/word/signed word/dword/signed dword) 1) ← (byte) 'b' -- _deref_pbuc1=vbuc2
lda #'b'
sta SCREEN+1
//SEG15 main::@return
//SEG16 [7] return
rts
}

View File

@ -0,0 +1,10 @@
(label) @1
(label) @begin
(label) @end
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@return
(byte*) main::SCREEN
(const byte*) main::SCREEN#0 SCREEN = ((byte*))(word/signed word/dword/signed dword) $400