mirror of
https://github.com/aNNiMON/Own-Programming-Language-Tutorial.git
synced 2024-09-20 00:34:20 +03:00
Show function call position in call stack
This commit is contained in:
parent
39b94a0113
commit
1fb9c8b3c5
@ -13,8 +13,16 @@ public final class CallStack {
|
|||||||
calls.clear();
|
calls.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized void enter(String name, Function function) {
|
public static synchronized void enter(String name, Function function, String position) {
|
||||||
calls.push(new CallInfo(name, function.toString()));
|
String func = function.toString();
|
||||||
|
if (func.contains("com.annimon.ownlang.modules")) {
|
||||||
|
func = func.replaceAll(
|
||||||
|
"com.annimon.ownlang.modules.(\\w+)\\.?\\1?", "module $1");
|
||||||
|
}
|
||||||
|
if (func.contains("\n")) {
|
||||||
|
func = func.substring(0, func.indexOf("\n")).trim();
|
||||||
|
}
|
||||||
|
calls.push(new CallInfo(name, func, position));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized void exit() {
|
public static synchronized void exit() {
|
||||||
@ -25,10 +33,14 @@ public final class CallStack {
|
|||||||
return calls;
|
return calls;
|
||||||
}
|
}
|
||||||
|
|
||||||
public record CallInfo(String name, String function) {
|
public record CallInfo(String name, String function, String position) {
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
if (position == null) {
|
||||||
return String.format("%s: %s", name, function);
|
return String.format("%s: %s", name, function);
|
||||||
|
} else {
|
||||||
|
return String.format("%s: %s %s", name, function, position);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package com.annimon.ownlang.parser;
|
package com.annimon.ownlang.util;
|
||||||
|
|
||||||
public record Pos(int row, int col) {
|
public record Pos(int row, int col) {
|
||||||
public static final Pos UNKNOWN = new Pos(-1, -1);
|
public static final Pos UNKNOWN = new Pos(-1, -1);
|
@ -1,4 +1,4 @@
|
|||||||
package com.annimon.ownlang.parser;
|
package com.annimon.ownlang.util;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@ -18,8 +18,10 @@ public record Range(Pos start, Pos end) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String format() {
|
public String format() {
|
||||||
if (isOnSameLine()) {
|
if (isEqualPosition())
|
||||||
return start.format();
|
return start.format();
|
||||||
|
else if (isOnSameLine()) {
|
||||||
|
return "[%d:%d~%d]".formatted(start.row(), start.col(), end.col());
|
||||||
} else {
|
} else {
|
||||||
return start.format() + "..." + end.format();
|
return start.format() + "..." + end.format();
|
||||||
}
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
package com.annimon.ownlang.util;
|
||||||
|
|
||||||
|
public interface SourceLocation {
|
||||||
|
|
||||||
|
default Range getRange() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
default String formatRange() {
|
||||||
|
final var range = getRange();
|
||||||
|
return range == null ? "" : range.format();
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
package com.annimon.ownlang.exceptions;
|
package com.annimon.ownlang.exceptions;
|
||||||
|
|
||||||
import com.annimon.ownlang.parser.Range;
|
import com.annimon.ownlang.util.Range;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base type for all lexer and parser exceptions
|
* Base type for all lexer and parser exceptions
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package com.annimon.ownlang.exceptions;
|
package com.annimon.ownlang.exceptions;
|
||||||
|
|
||||||
import com.annimon.ownlang.parser.Range;
|
import com.annimon.ownlang.util.Range;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -31,7 +31,7 @@ public class UserDefinedFunction implements Function {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Value execute(Value... values) {
|
public Value execute(Value[] values) {
|
||||||
final int size = values.length;
|
final int size = values.length;
|
||||||
final int requiredArgsCount = arguments.getRequiredArgumentsCount();
|
final int requiredArgsCount = arguments.getRequiredArgumentsCount();
|
||||||
if (size < requiredArgsCount) {
|
if (size < requiredArgsCount) {
|
||||||
|
@ -2,6 +2,8 @@ package com.annimon.ownlang.parser;
|
|||||||
|
|
||||||
import com.annimon.ownlang.exceptions.OwnLangParserException;
|
import com.annimon.ownlang.exceptions.OwnLangParserException;
|
||||||
import com.annimon.ownlang.parser.error.ParseError;
|
import com.annimon.ownlang.parser.error.ParseError;
|
||||||
|
import com.annimon.ownlang.util.Pos;
|
||||||
|
import com.annimon.ownlang.util.Range;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -8,6 +8,8 @@ import com.annimon.ownlang.lib.UserDefinedFunction;
|
|||||||
import com.annimon.ownlang.parser.ast.*;
|
import com.annimon.ownlang.parser.ast.*;
|
||||||
import com.annimon.ownlang.parser.error.ParseError;
|
import com.annimon.ownlang.parser.error.ParseError;
|
||||||
import com.annimon.ownlang.parser.error.ParseErrors;
|
import com.annimon.ownlang.parser.error.ParseErrors;
|
||||||
|
import com.annimon.ownlang.util.Pos;
|
||||||
|
import com.annimon.ownlang.util.Range;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@ -351,12 +353,14 @@ public final class Parser {
|
|||||||
|
|
||||||
private FunctionalExpression function(Expression qualifiedNameExpr) {
|
private FunctionalExpression function(Expression qualifiedNameExpr) {
|
||||||
// function(arg1, arg2, ...)
|
// function(arg1, arg2, ...)
|
||||||
|
final var startTokenIndex = index - 1;
|
||||||
consume(TokenType.LPAREN);
|
consume(TokenType.LPAREN);
|
||||||
final FunctionalExpression function = new FunctionalExpression(qualifiedNameExpr);
|
final FunctionalExpression function = new FunctionalExpression(qualifiedNameExpr);
|
||||||
while (!match(TokenType.RPAREN)) {
|
while (!match(TokenType.RPAREN)) {
|
||||||
function.addArgument(expression());
|
function.addArgument(expression());
|
||||||
match(TokenType.COMMA);
|
match(TokenType.COMMA);
|
||||||
}
|
}
|
||||||
|
function.setRange(getRange(startTokenIndex, index - 1));
|
||||||
return function;
|
return function;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package com.annimon.ownlang.parser;
|
package com.annimon.ownlang.parser;
|
||||||
|
|
||||||
|
import com.annimon.ownlang.util.Pos;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author aNNiMON
|
* @author aNNiMON
|
||||||
*/
|
*/
|
||||||
|
@ -2,6 +2,8 @@ package com.annimon.ownlang.parser.ast;
|
|||||||
|
|
||||||
import com.annimon.ownlang.exceptions.*;
|
import com.annimon.ownlang.exceptions.*;
|
||||||
import com.annimon.ownlang.lib.*;
|
import com.annimon.ownlang.lib.*;
|
||||||
|
import com.annimon.ownlang.util.Range;
|
||||||
|
import com.annimon.ownlang.util.SourceLocation;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -10,10 +12,12 @@ import java.util.List;
|
|||||||
*
|
*
|
||||||
* @author aNNiMON
|
* @author aNNiMON
|
||||||
*/
|
*/
|
||||||
public final class FunctionalExpression extends InterruptableNode implements Expression, Statement {
|
public final class FunctionalExpression extends InterruptableNode
|
||||||
|
implements Expression, Statement, SourceLocation {
|
||||||
|
|
||||||
public final Expression functionExpr;
|
public final Expression functionExpr;
|
||||||
public final List<Expression> arguments;
|
public final List<Expression> arguments;
|
||||||
|
private Range range;
|
||||||
|
|
||||||
public FunctionalExpression(Expression functionExpr) {
|
public FunctionalExpression(Expression functionExpr) {
|
||||||
this.functionExpr = functionExpr;
|
this.functionExpr = functionExpr;
|
||||||
@ -24,6 +28,15 @@ public final class FunctionalExpression extends InterruptableNode implements Exp
|
|||||||
arguments.add(arg);
|
arguments.add(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setRange(Range range) {
|
||||||
|
this.range = range;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Range getRange() {
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute() {
|
public void execute() {
|
||||||
eval();
|
eval();
|
||||||
@ -38,7 +51,7 @@ public final class FunctionalExpression extends InterruptableNode implements Exp
|
|||||||
values[i] = arguments.get(i).eval();
|
values[i] = arguments.get(i).eval();
|
||||||
}
|
}
|
||||||
final Function f = consumeFunction(functionExpr);
|
final Function f = consumeFunction(functionExpr);
|
||||||
CallStack.enter(functionExpr.toString(), f);
|
CallStack.enter(functionExpr.toString(), f, formatRange());
|
||||||
final Value result = f.execute(values);
|
final Value result = f.execute(values);
|
||||||
CallStack.exit();
|
CallStack.exit();
|
||||||
return result;
|
return result;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package com.annimon.ownlang.parser.error;
|
package com.annimon.ownlang.parser.error;
|
||||||
|
|
||||||
import com.annimon.ownlang.parser.Range;
|
import com.annimon.ownlang.util.Range;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package com.annimon.ownlang.parser.error;
|
package com.annimon.ownlang.parser.error;
|
||||||
|
|
||||||
import com.annimon.ownlang.Console;
|
import com.annimon.ownlang.Console;
|
||||||
import com.annimon.ownlang.parser.Pos;
|
import com.annimon.ownlang.util.Pos;
|
||||||
import com.annimon.ownlang.parser.Range;
|
import com.annimon.ownlang.util.Range;
|
||||||
import com.annimon.ownlang.stages.SourceLoaderStage;
|
import com.annimon.ownlang.stages.SourceLoaderStage;
|
||||||
import com.annimon.ownlang.stages.Stage;
|
import com.annimon.ownlang.stages.Stage;
|
||||||
import com.annimon.ownlang.stages.StagesData;
|
import com.annimon.ownlang.stages.StagesData;
|
||||||
|
@ -8,6 +8,7 @@ import com.annimon.ownlang.lib.*;
|
|||||||
import com.annimon.ownlang.parser.*;
|
import com.annimon.ownlang.parser.*;
|
||||||
import com.annimon.ownlang.parser.ast.BlockStatement;
|
import com.annimon.ownlang.parser.ast.BlockStatement;
|
||||||
import com.annimon.ownlang.parser.ast.Statement;
|
import com.annimon.ownlang.parser.ast.Statement;
|
||||||
|
import com.annimon.ownlang.util.Pos;
|
||||||
import com.annimon.ownlang.parser.visitors.PrintVisitor;
|
import com.annimon.ownlang.parser.visitors.PrintVisitor;
|
||||||
import com.annimon.ownlang.utils.repl.JLineConsole;
|
import com.annimon.ownlang.utils.repl.JLineConsole;
|
||||||
import com.annimon.ownlang.utils.repl.OwnLangCompleter;
|
import com.annimon.ownlang.utils.repl.OwnLangCompleter;
|
||||||
|
Loading…
Reference in New Issue
Block a user