Skip to content

Commit

Permalink
Merge cd369ee into d933bf1
Browse files Browse the repository at this point in the history
  • Loading branch information
smarr committed Jul 25, 2017
2 parents d933bf1 + cd369ee commit 6e29018
Show file tree
Hide file tree
Showing 8 changed files with 393 additions and 28 deletions.
30 changes: 30 additions & 0 deletions core-lib/TestSuite/LanguageTests.som
Original file line number Diff line number Diff line change
Expand Up @@ -709,4 +709,34 @@ class LanguageTests usingPlatform: platform testFramework: minitest = Value (
self assert: 42 equals: (a at: i) aNumber ]
)
) : ( TEST_CONTEXT = () )
public class InitializerForLocalVariables = TestContext ()(
public testSimpleInitializers = (
| cnt ::= 0.
inc = 1. |
assert: cnt equals: 0.
assert: inc equals: 1.
cnt:: cnt + inc.
cnt:: cnt + inc.
assert: cnt equals: 2.
assert: inc equals: 1.
)
private myself = ( ^ self )
private ret: o = ( ^ o )
public testMoreComplexExpressions = (
| zero ::= 4 - 8 + 4.
obj = myself.
o = ret: obj. |
assert: zero equals: 0.
assert: obj is: self.
assert: o is: self.
)
) : ( TEST_CONTEXT = () )
)
8 changes: 5 additions & 3 deletions src/som/compiler/Lexer.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ int incPtr(final int val) {
}
}

private final String content;
protected final String content;

private boolean peekDone;
private LexerState state;
Expand Down Expand Up @@ -194,7 +194,7 @@ private Symbol doSym() {
if (isDigit(nextChar())) {
lexNumber();
} else {
match(Symbol.Minus);
lexOperator();
}
} else if (currentChar() == '<') {
state.incPtr();
Expand All @@ -213,7 +213,7 @@ private Symbol doSym() {
}
} else if (isOperator(currentChar())) {
lexOperator();
} else if (Character.isLetter(currentChar())) {
} else if (Character.isLetter(currentChar()) || currentChar() == '_') {
state.set(Symbol.Identifier);
while (isIdentifierChar(currentChar())) {
state.text.append(bufchar(state.incPtr()));
Expand Down Expand Up @@ -325,6 +325,8 @@ private void lexOperator() {
match(Symbol.At);
} else if (currentChar() == '%') {
match(Symbol.Per);
} else if (currentChar() == '-') {
match(Symbol.Minus);
}
}

Expand Down
17 changes: 12 additions & 5 deletions src/som/compiler/MethodBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@
import som.compiler.MixinBuilder.MixinDefinitionId;
import som.compiler.ProgramDefinitionError.SemanticDefinitionError;
import som.compiler.Variable.Argument;
import som.compiler.Variable.ImmutableLocal;
import som.compiler.Variable.Internal;
import som.compiler.Variable.Local;
import som.compiler.Variable.MutableLocal;
import som.interpreter.InliningVisitor;
import som.interpreter.LexicalScope.MethodScope;
import som.interpreter.LexicalScope.MixinScope;
Expand Down Expand Up @@ -337,21 +339,26 @@ public void addArgument(final String arg, final SourceSection source) {
arguments.put(arg, argument);
}

public Local addLocal(final String name, final SourceSection source)
throws MethodDefinitionError {
public Local addLocal(final String name, final boolean immutable,
final SourceSection source) throws MethodDefinitionError {
if (arguments.containsKey(name)) {
throw new MethodDefinitionError("Method already defines argument " + name + ". Can't define local variable with same name.", source);
}

Local l = new Local(name, source);
Local l;
if (immutable) {
l = new ImmutableLocal(name, source);
} else {
l = new MutableLocal(name, source);
}
l.init(currentScope.getFrameDescriptor().addFrameSlot(l));
locals.put(name, l);
return l;
}

public Local addLocalAndUpdateScope(final String name,
public Local addLocalAndUpdateScope(final String name, final boolean immutable,
final SourceSection source) throws MethodDefinitionError {
Local l = addLocal(name, source);
Local l = addLocal(name, immutable, source);
currentScope.addVariable(l);
return l;
}
Expand Down
10 changes: 9 additions & 1 deletion src/som/compiler/NumeralParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

import java.math.BigInteger;

import som.VM;


public class NumeralParser {

Expand Down Expand Up @@ -88,7 +90,13 @@ private long calculateNumberWithRadixLong() {
v = c - 'A' + 10 /* A has value 10 */;
}

result = Math.addExact(result, (long) (Math.pow(r, length - i - 1) * v));
try {
result = Math.addExact(result, (long) (Math.pow(r, length - i - 1) * v));
} catch (ArithmeticException e) {
// TODO: need to overflow into BigInteger
VM.errorPrintln("Warning: Parsed Integer literal which did not fit into long. " + lexer.getCurrentLineNumber() + ":" + lexer.getCurrentColumn());
return result;
}
}
return result;
}
Expand Down
105 changes: 89 additions & 16 deletions src/som/compiler/Parser.java
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,12 @@

public class Parser {

private final Lexer lexer;
protected final Lexer lexer;
private final Source source;

private final SomLanguage language;

private Symbol sym;
protected Symbol sym;
private String text;
private Symbol nextSym;
private String nextText;
Expand Down Expand Up @@ -288,7 +288,16 @@ public SourceCoordinate getCoordinate() {
return lexer.getStartCoordinate();
}

private void compatibilityNewspeakVersionAndFileCategory() throws ParseError {
if (sym == Identifier && "Newspeak3".equals(text)) {
expect(Identifier, KeywordTag.class);
expect(STString, LiteralTag.class);
}
}

public MixinBuilder moduleDeclaration() throws ProgramDefinitionError {
compatibilityNewspeakVersionAndFileCategory();

comments();
return classDeclaration(null, AccessModifier.PUBLIC);
}
Expand Down Expand Up @@ -579,6 +588,8 @@ private void slotDefinition(final MixinBuilder mxnBuilder)
SourceCoordinate coord = getCoordinate();
AccessModifier acccessModifier = accessModifier();

comments();

String slotName = slotDecl();
boolean immutable;
ExpressionNode init;
Expand Down Expand Up @@ -609,7 +620,10 @@ private AccessModifier accessModifier() {
}

private String slotDecl() throws ParseError {
return identifier();
String id = identifier();

new TypeParser(this).parseType();
return id;
}

private void initExprs(final MixinBuilder mxnBuilder) throws ProgramDefinitionError {
Expand Down Expand Up @@ -726,7 +740,7 @@ private void expect(final Symbol s, final String msg,
throw new ParseError(msg, s, this);
}

private void expect(final Symbol s, final Class<? extends Tags> tag) throws ParseError {
protected void expect(final Symbol s, final Class<? extends Tags> tag) throws ParseError {
expect(s, "Unexpected symbol. Expected %(expected)s, but found %(found)s", tag);
}

Expand Down Expand Up @@ -784,6 +798,8 @@ private void messagePattern(final MethodBuilder builder) throws ParseError {
binaryPattern(builder);
break;
}

new TypeParser(this).parseReturnType();
}

protected void unaryPattern(final MethodBuilder builder) throws ParseError {
Expand Down Expand Up @@ -873,34 +889,74 @@ protected String setterKeyword() throws ParseError {
private String argument() throws ParseError {
SourceCoordinate coord = getCoordinate();
String id = identifier();

new TypeParser(this).parseType();

language.getVM().reportSyntaxElement(ArgumentTag.class, getSource(coord));
return id;
}

private ExpressionNode blockContents(final MethodBuilder builder)
throws ProgramDefinitionError {
comments();
List<ExpressionNode> expressions = new ArrayList<ExpressionNode>();

if (accept(Or, DelimiterOpeningTag.class)) {
locals(builder);
locals(builder, expressions);
expect(Or, DelimiterClosingTag.class);
}
builder.setVarsOnMethodScope();
return blockBody(builder);
return blockBody(builder, expressions);
}

private void locals(final MethodBuilder builder) throws ParseError, MethodDefinitionError {
while (sym == Identifier) {
SourceCoordinate coord = getCoordinate();
String id = identifier();
SourceSection source = getSource(coord);
builder.addLocal(id, source);
language.getVM().reportSyntaxElement(LocalVariableTag.class, source);
private void locals(final MethodBuilder builder,
final List<ExpressionNode> expressions) throws ProgramDefinitionError {
// Newspeak-speak: we do not support simSlotDecls, i.e.,
// simultaneous slots clauses (spec 6.3.2)
while (sym != Or) {
localDefinition(builder, expressions);
}
}

private ExpressionNode blockBody(final MethodBuilder builder) throws ProgramDefinitionError {
private void localDefinition(final MethodBuilder builder,
final List<ExpressionNode> expressions) throws ProgramDefinitionError {
comments();
if (sym == Or) { return; }

SourceCoordinate coord = getCoordinate();
String slotName = slotDecl();
SourceSection source = getSource(coord);

language.getVM().reportSyntaxElement(LocalVariableTag.class, source);

boolean immutable;
ExpressionNode initializer;

if (accept(Equal, KeywordTag.class)) {
immutable = true;
initializer = expression(builder);
expect(Period, StatementSeparatorTag.class);
} else if (accept(SlotMutableAssign, KeywordTag.class)) {
immutable = false;
initializer = expression(builder);
expect(Period, StatementSeparatorTag.class);
} else {
immutable = false;
initializer = null;
}

Local local = builder.addLocal(slotName, immutable, source);

if (initializer != null) {
SourceSection write = getSource(coord);
ExpressionNode writeNode = local.getWriteNode(0, initializer, write);
expressions.add(writeNode);
}
}

private ExpressionNode blockBody(final MethodBuilder builder,
final List<ExpressionNode> expressions) throws ProgramDefinitionError {
SourceCoordinate coord = getCoordinate();
List<ExpressionNode> expressions = new ArrayList<ExpressionNode>();

boolean sawPeriod = true;

Expand Down Expand Up @@ -1006,19 +1062,27 @@ private ExpressionNode primary(final MethodBuilder builder) throws ProgramDefini
// Parse true, false, and nil as keyword-like constructs
// (cf. Newspeak spec on reserved words)
if (acceptIdentifier("true", LiteralTag.class)) {
comments();
return new TrueLiteralNode(getSource(coord));
}

if (acceptIdentifier("false", LiteralTag.class)) {
comments();
return new FalseLiteralNode(getSource(coord));
}

if (acceptIdentifier("nil", LiteralTag.class)) {
comments();
return new NilLiteralNode(getSource(coord));
}
if ("outer".equals(text)) {
return outerSend(builder);
}

SSymbol selector = unarySelector();

comments();

return builder.getImplicitReceiverSend(selector, getSource(coord));
}
case NewTerm: {
Expand Down Expand Up @@ -1059,8 +1123,12 @@ private ExpressionNode outerSend(final MethodBuilder builder)
expectIdentifier("outer", KeywordTag.class);
String outer = identifier();

comments();

ExpressionNode operand = builder.getOuterRead(outer, getSource(coord));
operand = binaryConsecutiveMessages(builder, operand, false, null);

comments();
return operand;
}

Expand Down Expand Up @@ -1117,6 +1185,8 @@ protected ExpressionNode unaryMessage(final ExpressionNode receiver,
final boolean eventualSend, final SourceSection sendOperator) throws ParseError {
SourceCoordinate coord = getCoordinate();
SSymbol selector = unarySelector();

comments();
return createMessageSend(selector, new ExpressionNode[] {receiver},
eventualSend, getSource(coord), sendOperator, language);
}
Expand Down Expand Up @@ -1187,7 +1257,10 @@ protected ExpressionNode keywordMessage(final MethodBuilder builder,

do {
kw.append(keyword());
comments();

arguments.add(formula(builder));
comments();
}
while (sym == Keyword);

Expand Down Expand Up @@ -1314,7 +1387,7 @@ private Local getLoopIdx(final MethodBuilder builder,
// if it is a literal, we still need a memory location for counting, so,
// add a synthetic local
loopIdx = builder.addLocalAndUpdateScope(
"!i" + SourceCoordinate.getLocationQualifier(source), source);
"!i" + SourceCoordinate.getLocationQualifier(source), false, source);
}
return loopIdx;
}
Expand Down
Loading

0 comments on commit 6e29018

Please sign in to comment.