Skip to content

Commit d3dd8fe

Browse files
committed
Source located function, class and arguments
1 parent 2bb5e45 commit d3dd8fe

File tree

9 files changed

+66
-22
lines changed

9 files changed

+66
-22
lines changed

ownlang-core/src/main/java/com/annimon/ownlang/exceptions/ArgumentsMismatchException.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.annimon.ownlang.exceptions;
22

3+
import com.annimon.ownlang.util.Range;
4+
35
public final class ArgumentsMismatchException extends OwnLangRuntimeException {
46

57
public ArgumentsMismatchException() {
@@ -8,4 +10,8 @@ public ArgumentsMismatchException() {
810
public ArgumentsMismatchException(String message) {
911
super(message);
1012
}
13+
14+
public ArgumentsMismatchException(String message, Range range) {
15+
super(message, range);
16+
}
1117
}

ownlang-parser/src/main/java/com/annimon/ownlang/lib/ClassMethod.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@
22

33
import com.annimon.ownlang.parser.ast.Arguments;
44
import com.annimon.ownlang.parser.ast.Statement;
5+
import com.annimon.ownlang.util.Range;
56

67
public class ClassMethod extends UserDefinedFunction {
78

89
public final ClassInstanceValue classInstance;
910

10-
public ClassMethod(Arguments arguments, Statement body, ClassInstanceValue classInstance) {
11-
super(arguments, body);
11+
public ClassMethod(Arguments arguments, Statement body, ClassInstanceValue classInstance, Range range) {
12+
super(arguments, body, range);
1213
this.classInstance = classInstance;
1314
}
1415

ownlang-parser/src/main/java/com/annimon/ownlang/lib/UserDefinedFunction.java

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,30 @@
55
import com.annimon.ownlang.parser.ast.Arguments;
66
import com.annimon.ownlang.parser.ast.ReturnStatement;
77
import com.annimon.ownlang.parser.ast.Statement;
8+
import com.annimon.ownlang.util.Range;
9+
import com.annimon.ownlang.util.SourceLocation;
810

911
/**
1012
*
1113
* @author aNNiMON
1214
*/
13-
public class UserDefinedFunction implements Function {
15+
public class UserDefinedFunction implements Function, SourceLocation {
1416

1517
public final Arguments arguments;
1618
public final Statement body;
17-
18-
public UserDefinedFunction(Arguments arguments, Statement body) {
19+
private final Range range;
20+
21+
public UserDefinedFunction(Arguments arguments, Statement body, Range range) {
1922
this.arguments = arguments;
2023
this.body = body;
24+
this.range = range;
2125
}
22-
26+
27+
@Override
28+
public Range getRange() {
29+
return range;
30+
}
31+
2332
@Override
2433
public int getArgsCount() {
2534
return arguments.size();
@@ -35,13 +44,15 @@ public Value execute(Value[] values) {
3544
final int size = values.length;
3645
final int requiredArgsCount = arguments.getRequiredArgumentsCount();
3746
if (size < requiredArgsCount) {
38-
throw new ArgumentsMismatchException(String.format(
39-
"Arguments count mismatch. Required %d, got %d", requiredArgsCount, size));
47+
String error = String.format(
48+
"Arguments count mismatch. Required %d, got %d", requiredArgsCount, size);
49+
throw new ArgumentsMismatchException(error, arguments.getRange());
4050
}
4151
final int totalArgsCount = getArgsCount();
4252
if (size > totalArgsCount) {
43-
throw new ArgumentsMismatchException(String.format(
44-
"Arguments count mismatch. Total %d, got %d", totalArgsCount, size));
53+
String error = String.format(
54+
"Arguments count mismatch. Total %d, got %d", totalArgsCount, size);
55+
throw new ArgumentsMismatchException(error, arguments.getRange());
4556
}
4657

4758
try {

ownlang-parser/src/main/java/com/annimon/ownlang/parser/Parser.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -290,16 +290,18 @@ private ForeachMapStatement foreachMapStatement() {
290290

291291
private FunctionDefineStatement functionDefine() {
292292
// def name(arg1, arg2 = value) { ... } || def name(args) = expr
293+
final var startTokenIndex = index - 1;
293294
final String name = consume(TokenType.WORD).text();
294295
final Arguments arguments = arguments();
295296
final Statement body = statementBody();
296-
return new FunctionDefineStatement(name, arguments, body);
297+
return new FunctionDefineStatement(name, arguments, body, getRange(startTokenIndex, index - 1));
297298
}
298299

299300
private Arguments arguments() {
300301
// (arg1, arg2, arg3 = expr1, arg4 = expr2)
301302
final Arguments arguments = new Arguments();
302303
boolean startsOptionalArgs = false;
304+
final var startTokenIndex = index;
303305
consume(TokenType.LPAREN);
304306
while (!match(TokenType.RPAREN)) {
305307
final String name = consume(TokenType.WORD).text();
@@ -313,6 +315,7 @@ private Arguments arguments() {
313315
}
314316
match(TokenType.COMMA);
315317
}
318+
arguments.setRange(getRange(startTokenIndex, index - 1));
316319
return arguments;
317320
}
318321

@@ -802,9 +805,10 @@ private Expression primary() {
802805
}
803806
if (match(TokenType.DEF)) {
804807
// anonymous function def(args) ...
808+
final var startTokenIndex = index - 1;
805809
final Arguments arguments = arguments();
806810
final Statement statement = statementBody();
807-
return new ValueExpression(new UserDefinedFunction(arguments, statement));
811+
return new ValueExpression(new UserDefinedFunction(arguments, statement, getRange(startTokenIndex, index - 1)));
808812
}
809813
return variable();
810814
}

ownlang-parser/src/main/java/com/annimon/ownlang/parser/ast/Arguments.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
11
package com.annimon.ownlang.parser.ast;
22

3+
import com.annimon.ownlang.util.Range;
4+
import com.annimon.ownlang.util.SourceLocation;
35
import java.util.ArrayList;
46
import java.util.Iterator;
57
import java.util.List;
68

7-
public final class Arguments implements Iterable<Argument> {
9+
public final class Arguments implements Iterable<Argument>, SourceLocation {
810

911
private final List<Argument> arguments;
12+
private Range range;
1013
private int requiredArgumentsCount;
1114

1215
public Arguments() {
1316
arguments = new ArrayList<>();
1417
requiredArgumentsCount = 0;
1518
}
16-
19+
1720
public void addRequired(String name) {
1821
arguments.add(new Argument(name));
1922
requiredArgumentsCount++;
@@ -35,6 +38,15 @@ public int size() {
3538
return arguments.size();
3639
}
3740

41+
public void setRange(Range range) {
42+
this.range = range;
43+
}
44+
45+
@Override
46+
public Range getRange() {
47+
return range;
48+
}
49+
3850
@Override
3951
public Iterator<Argument> iterator() {
4052
return arguments.iterator();

ownlang-parser/src/main/java/com/annimon/ownlang/parser/ast/FunctionDefineStatement.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,35 @@
22

33
import com.annimon.ownlang.lib.ScopeHandler;
44
import com.annimon.ownlang.lib.UserDefinedFunction;
5+
import com.annimon.ownlang.util.Range;
6+
import com.annimon.ownlang.util.SourceLocation;
57

68
/**
79
*
810
* @author aNNiMON
911
*/
10-
public final class FunctionDefineStatement implements Statement {
12+
public final class FunctionDefineStatement implements Statement, SourceLocation {
1113

1214
public final String name;
1315
public final Arguments arguments;
1416
public final Statement body;
17+
private final Range range;
1518

16-
public FunctionDefineStatement(String name, Arguments arguments, Statement body) {
19+
public FunctionDefineStatement(String name, Arguments arguments, Statement body, Range range) {
1720
this.name = name;
1821
this.arguments = arguments;
1922
this.body = body;
23+
this.range = range;
24+
}
25+
26+
@Override
27+
public Range getRange() {
28+
return range;
2029
}
2130

2231
@Override
2332
public void execute() {
24-
ScopeHandler.setFunction(name, new UserDefinedFunction(arguments, body));
33+
ScopeHandler.setFunction(name, new UserDefinedFunction(arguments, body, range));
2534
}
2635

2736
@Override

ownlang-parser/src/main/java/com/annimon/ownlang/parser/ast/ObjectCreationExpression.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public Value eval() {
3838
return instantiable.newInstance(ctorArgs());
3939
}
4040
}
41-
throw new UnknownClassException(className, getRange());
41+
throw new UnknownClassException(className, range);
4242
}
4343

4444
// Create an instance and put evaluated fields with method declarations
@@ -49,7 +49,7 @@ public Value eval() {
4949
instance.addField(fieldName, f.eval());
5050
}
5151
for (FunctionDefineStatement m : cd.methods) {
52-
instance.addMethod(m.name, new ClassMethod(m.arguments, m.body, instance));
52+
instance.addMethod(m.name, new ClassMethod(m.arguments, m.body, instance, m.getRange()));
5353
}
5454

5555
// Call a constructor

ownlang-parser/src/main/java/com/annimon/ownlang/parser/optimization/OptimizationVisitor.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ public Node visit(FunctionDefineStatement s, T t) {
174174

175175
final Node body = s.body.accept(this, t);
176176
if (changed || body != s.body) {
177-
return new FunctionDefineStatement(s.name, newArgs, consumeStatement(body));
177+
return new FunctionDefineStatement(s.name, newArgs, consumeStatement(body), s.getRange());
178178
}
179179
return s;
180180
}
@@ -423,7 +423,7 @@ public UserDefinedFunction visit(UserDefinedFunction s, T t) {
423423

424424
final Node body = s.body.accept(this, t);
425425
if (changed || body != s.body) {
426-
return new UserDefinedFunction(newArgs, consumeStatement(body));
426+
return new UserDefinedFunction(newArgs, consumeStatement(body), s.getRange());
427427
}
428428
return s;
429429
}
@@ -432,6 +432,7 @@ public UserDefinedFunction visit(UserDefinedFunction s, T t) {
432432

433433
protected boolean visit(final Arguments in, final Arguments out, T t) {
434434
boolean changed = false;
435+
out.setRange(in.getRange());
435436
for (Argument argument : in) {
436437
final Expression valueExpr = argument.valueExpr();
437438
if (valueExpr == null) {

ownlang-parser/src/test/java/com/annimon/ownlang/parser/ProgramsTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ public void testProgram(InputSource inputSource) {
9797
.perform(stagesData, ex.getParseErrors());
9898
fail(inputSource + "\n" + error, ex);
9999
} catch (Exception oae) {
100-
fail(inputSource.toString(), oae);
101100
Console.handleException(stagesData, Thread.currentThread(), oae);
101+
fail(inputSource.toString(), oae);
102102
}
103103
}
104104

0 commit comments

Comments
 (0)