From fa5cf71eda0c500b561abf778bf40470d7628363 Mon Sep 17 00:00:00 2001 From: Piotr Fusik Date: Thu, 27 Jun 2024 19:57:58 +0200 Subject: [PATCH] [error] `base` in static context. --- Sema.fu | 7 +++++-- libfut.cpp | 6 +++++- libfut.cs | 6 +++++- libfut.js | 6 +++++- test/error/ConstValueBase.fu | 2 +- test/error/MethodBaseNoBase.fu | 9 ++++----- test/error/MethodBaseNotFound.fu | 7 +++---- test/error/MethodBaseNotMethod.fu | 9 ++++----- test/error/MethodBaseStatic.fu | 12 ++++++++++++ 9 files changed, 44 insertions(+), 20 deletions(-) create mode 100644 test/error/MethodBaseStatic.fu diff --git a/Sema.fu b/Sema.fu index 7a06d2da..5d4c6388 100644 --- a/Sema.fu +++ b/Sema.fu @@ -252,10 +252,13 @@ public class FuSema FuScope scope; bool isBase = left is FuSymbolReference baseSymbol && baseSymbol.Symbol.Id == FuId.BasePtr; if (isBase) { - if (this.CurrentMethod == null || !(this.CurrentMethod.Parent.Parent is FuClass baseClass)) + if (this.CurrentMethod == null) + return PoisonError(left, "'base' invalid outside methods"); + if (this.CurrentMethod.IsStatic()) + return PoisonError(left, "'base' invalid in static context"); + if (!(this.CurrentMethod.Parent.Parent is FuClass baseClass)) return PoisonError(left, "No base class"); scope = baseClass; - // TODO: static? } else if (left is FuSymbolReference leftSymbol && leftSymbol.Symbol is FuScope obj) scope = obj; diff --git a/libfut.cpp b/libfut.cpp index fb918e2d..244117a4 100644 --- a/libfut.cpp +++ b/libfut.cpp @@ -4655,8 +4655,12 @@ std::shared_ptr FuSema::visitSymbolReference(std::shared_ptr(left.get())) && baseSymbol->symbol->id == FuId::basePtr; if (isBase) { + if (this->currentMethod == nullptr) + return poisonError(left.get(), "'base' invalid outside methods"); + if (this->currentMethod->isStatic()) + return poisonError(left.get(), "'base' invalid in static context"); const FuClass * baseClass; - if (this->currentMethod == nullptr || !(baseClass = dynamic_cast(this->currentMethod->parent->parent))) + if (!(baseClass = dynamic_cast(this->currentMethod->parent->parent))) return poisonError(left.get(), "No base class"); scope = baseClass; } diff --git a/libfut.cs b/libfut.cs index 38ca2797..758f024e 100644 --- a/libfut.cs +++ b/libfut.cs @@ -4911,7 +4911,11 @@ FuExpr VisitSymbolReference(FuSymbolReference expr) FuScope scope; bool isBase = left is FuSymbolReference baseSymbol && baseSymbol.Symbol.Id == FuId.BasePtr; if (isBase) { - if (this.CurrentMethod == null || !(this.CurrentMethod.Parent.Parent is FuClass baseClass)) + if (this.CurrentMethod == null) + return PoisonError(left, "'base' invalid outside methods"); + if (this.CurrentMethod.IsStatic()) + return PoisonError(left, "'base' invalid in static context"); + if (!(this.CurrentMethod.Parent.Parent is FuClass baseClass)) return PoisonError(left, "No base class"); scope = baseClass; } diff --git a/libfut.js b/libfut.js index e8a20505..e7a5b87f 100644 --- a/libfut.js +++ b/libfut.js @@ -5147,8 +5147,12 @@ export class FuSema let baseSymbol; let isBase = (baseSymbol = left) instanceof FuSymbolReference && baseSymbol.symbol.id == FuId.BASE_PTR; if (isBase) { + if (this.#currentMethod == null) + return this.#poisonError(left, "'base' invalid outside methods"); + if (this.#currentMethod.isStatic()) + return this.#poisonError(left, "'base' invalid in static context"); let baseClass; - if (this.#currentMethod == null || !((baseClass = this.#currentMethod.parent.parent) instanceof FuClass)) + if (!((baseClass = this.#currentMethod.parent.parent) instanceof FuClass)) return this.#poisonError(left, "No base class"); scope = baseClass; } diff --git a/test/error/ConstValueBase.fu b/test/error/ConstValueBase.fu index 5b03a751..b2d40d80 100644 --- a/test/error/ConstValueBase.fu +++ b/test/error/ConstValueBase.fu @@ -1,6 +1,6 @@ public static class Test { - const int Foo = base.Bar(); //ERROR: No base class + const int Foo = base.Bar(); //ERROR: 'base' invalid outside methods public static bool Run() { diff --git a/test/error/MethodBaseNoBase.fu b/test/error/MethodBaseNoBase.fu index 0e566a2b..86669a0f 100644 --- a/test/error/MethodBaseNoBase.fu +++ b/test/error/MethodBaseNoBase.fu @@ -1,7 +1,6 @@ -public static class Test +public class Test { - public static bool Run() - { - return base.Foo(); //ERROR: No base class - } + bool Foo() => base.Bar(); //ERROR: No base class + + public static bool Run() => true; } diff --git a/test/error/MethodBaseNotFound.fu b/test/error/MethodBaseNotFound.fu index 3903de99..4ae728e2 100644 --- a/test/error/MethodBaseNotFound.fu +++ b/test/error/MethodBaseNotFound.fu @@ -4,8 +4,7 @@ public class Base public class Test : Base { - public static bool Run() - { - return base.Foo(); //ERROR: 'Foo' not found - } + bool Foo() => base.Bar(); //ERROR: 'Bar' not found + + public static bool Run() => true; } diff --git a/test/error/MethodBaseNotMethod.fu b/test/error/MethodBaseNotMethod.fu index f503869b..e5399463 100644 --- a/test/error/MethodBaseNotMethod.fu +++ b/test/error/MethodBaseNotMethod.fu @@ -1,12 +1,11 @@ public class Base { - internal int Foo; + internal int Bar; } public class Test : Base { - public static bool Run() - { - return base.Foo(); //ERROR: Expected a method - } + bool Foo() => base.Bar(); //ERROR: Expected a method + + public static bool Run() => true; } diff --git a/test/error/MethodBaseStatic.fu b/test/error/MethodBaseStatic.fu new file mode 100644 index 00000000..68d75e8d --- /dev/null +++ b/test/error/MethodBaseStatic.fu @@ -0,0 +1,12 @@ +public abstract class Base +{ + protected bool Foo() => true; +} + +public class Test : Base +{ + public static bool Run() + { + return base.Foo(); //ERROR: 'base' invalid in static context + } +}