Include correct tokens in pattern mismatch errors
This commit is contained in:
parent
7d006d8889
commit
93215cd294
6
AST.cs
6
AST.cs
@ -42,9 +42,9 @@ public partial record SimplePattern
|
||||
}
|
||||
}
|
||||
|
||||
public abstract record Binding(Expr Value);
|
||||
public record VarBinding(Pattern Pattern, Expr Value) : Binding(Value);
|
||||
public record FuncBinding(Token Name, Pattern[] Params, Expr Value) : Binding(Value)
|
||||
public abstract record Binding(Expr Value, Token Start);
|
||||
public record VarBinding(Pattern Pattern, Expr Value) : Binding(Value, Pattern.Start);
|
||||
public record FuncBinding(Token Name, Pattern[] Params, Expr Value) : Binding(Value, Name)
|
||||
{
|
||||
public override string ToString()
|
||||
{
|
||||
|
@ -38,7 +38,6 @@ public class Env
|
||||
var name = (string)identifier.Literal!;
|
||||
if (values.ContainsKey(name))
|
||||
{
|
||||
// TODO use real location info
|
||||
throw new RuntimeError(identifier, $"Cannot redefine variable {name} in same scope.");
|
||||
}
|
||||
values[name] = value;
|
||||
@ -56,7 +55,6 @@ public class Env
|
||||
{
|
||||
return enclosing[identifier];
|
||||
}
|
||||
// TODO use real location info
|
||||
throw new RuntimeError(identifier, $"Undefined variable {name}.");
|
||||
}
|
||||
}
|
||||
@ -75,12 +73,19 @@ public class Interpreter : AST.IExprVisitor<Env, object>
|
||||
}
|
||||
}
|
||||
|
||||
private class PatternTagMismatchException : Exception
|
||||
private class PatternMismatchException : Exception
|
||||
{
|
||||
public PatternTagMismatchException(string patternTag, string valueTag) : base($"Pattern tag {patternTag} does not match value tag {valueTag}.") { }
|
||||
public readonly Token Start;
|
||||
public PatternMismatchException(Token start, string message) : base(message)
|
||||
{
|
||||
Start = start;
|
||||
}
|
||||
}
|
||||
|
||||
private class PatternTypeMismatchException : Exception { }
|
||||
private class VariantTagMismatchException : PatternMismatchException
|
||||
{
|
||||
public VariantTagMismatchException(Token start, string patternTag, string valueTag) : base(start, $"Pattern tag {patternTag} does not match value tag {valueTag}.") { }
|
||||
}
|
||||
|
||||
class PatternBinder : AST.IPatternVisitor<(object, Env), ValueTuple>
|
||||
{
|
||||
@ -110,7 +115,7 @@ public class Interpreter : AST.IExprVisitor<Env, object>
|
||||
}
|
||||
return ValueTuple.Create();
|
||||
}
|
||||
throw new PatternTypeMismatchException();
|
||||
throw new PatternMismatchException(pattern.Start, "Matched value {obj} is not a record.");
|
||||
}
|
||||
|
||||
public ValueTuple visitSimplePatternPattern((object, Env) context, AST.SimplePattern pattern)
|
||||
@ -133,7 +138,7 @@ public class Interpreter : AST.IExprVisitor<Env, object>
|
||||
var tag = (string)pattern.Tag.Literal!;
|
||||
if (v.Tag != tag)
|
||||
{
|
||||
throw new PatternTagMismatchException(tag, v.Tag);
|
||||
throw new VariantTagMismatchException(pattern.Start, tag, v.Tag);
|
||||
}
|
||||
if (v.Value == null && pattern.Argument == null)
|
||||
{
|
||||
@ -143,10 +148,9 @@ public class Interpreter : AST.IExprVisitor<Env, object>
|
||||
{
|
||||
return pattern.Argument.accept((v.Value, env), this);
|
||||
}
|
||||
throw new PatternTypeMismatchException();
|
||||
throw new PatternMismatchException(pattern.Start, "Variant pattern arity does not match variant value.");
|
||||
}
|
||||
// TODO throw a better exception
|
||||
throw new Exception($"Not a variant.");
|
||||
throw new PatternMismatchException(pattern.Start, $"Matched value {obj} is not a variant.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -448,9 +452,10 @@ public class Interpreter : AST.IExprVisitor<Env, object>
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// TODO use real info
|
||||
var tok = new Token(TokenType.Let, "let", null, new(0, 1, 1), new(0, 1, 1));
|
||||
throw new RuntimeError(tok, e.Message);
|
||||
var start = e is PatternMismatchException ?
|
||||
((PatternMismatchException)e).Start :
|
||||
binding.Start;
|
||||
throw new RuntimeError(start, e.Message);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -593,8 +598,6 @@ public class Interpreter : AST.IExprVisitor<Env, object>
|
||||
public object visitWhenExpr(Env env, AST.When expr)
|
||||
{
|
||||
var head = evaluate(env, expr.Head);
|
||||
// TODO use real info
|
||||
var tok = new Token(TokenType.When, "when", null, new(0, 1, 1), new(0, 1, 1));
|
||||
foreach (var c in expr.Cases)
|
||||
{
|
||||
try
|
||||
@ -603,15 +606,15 @@ public class Interpreter : AST.IExprVisitor<Env, object>
|
||||
c.Pattern.accept((head, newEnv), new PatternBinder());
|
||||
return evaluate(newEnv, c.Value);
|
||||
}
|
||||
catch (PatternTagMismatchException)
|
||||
catch (VariantTagMismatchException)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
catch (PatternTypeMismatchException e)
|
||||
catch (PatternMismatchException e)
|
||||
{
|
||||
throw new RuntimeError(tok, e.Message);
|
||||
throw new RuntimeError(e.Start, e.Message);
|
||||
}
|
||||
}
|
||||
throw new RuntimeError(tok, "No matching patterns.");
|
||||
throw new RuntimeError(expr.Start, "No matching patterns.");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user