diff --git a/.semaphore/semaphore.yml b/.semaphore/semaphore.yml index 0f86b225..756bed80 100644 --- a/.semaphore/semaphore.yml +++ b/.semaphore/semaphore.yml @@ -24,18 +24,3 @@ blocks: - build/sysroot/usr/local/bin/flaxc -sysroot build/sysroot -profile -run -backend llvm build/tester.flx - build/sysroot/usr/local/bin/flaxc -sysroot build/sysroot -profile -run -backend interp build/tester.flx - build/sysroot/usr/local/bin/flaxc -sysroot build/sysroot -profile build/tester.flx && ./tester - - name: "macos-build" - task: - agent: - machine: - type: a1-standard-4 - os_image: macos-mojave - jobs: - - name: build - commands: - - checkout - - HOMEBREW_NO_INSTALL_CLEANUP=1 brew install llvm@7 mpfr libffi - - PATH="/usr/local/opt/llvm@7/bin:$PATH" LLVM_CONFIG=llvm-config make -j4 build - - build/sysroot/usr/local/bin/flaxc -sysroot build/sysroot -profile -run -backend llvm build/tester.flx - - build/sysroot/usr/local/bin/flaxc -sysroot build/sysroot -profile -run -backend interp build/tester.flx - - build/sysroot/usr/local/bin/flaxc -sysroot build/sysroot -profile build/tester.flx && ./tester diff --git a/README.md b/README.md index 33490e7b..3a04b8ff 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ A low level, general-purpose language with high level syntax and expressibility. I work on Flax in my spare time, and as the lone developer I cannot guarantee continuous development. I'm no famous artist but this is my magnum opus, so it'll not be abandoned anytime soon. -Development is currently on hiatus. Work will resume NET 2019-12-09. +Development is currently on hiatus. Regular work will resume NET 2019-12-09. ### Language Goals @@ -44,19 +44,24 @@ Development is currently on hiatus. Work will resume NET 2019-12-09. ### Current Features -- Structs, classes, unions, enums +- Structs, unions, enums - Arrays (fixed and dynamic), slices - Pointer manipulation/arithmetic - Operator overloading - Generic functions and types - Type inference (including for generics) - Full compile-time execution (of arbitrary code) +- Classes, including virtual dispatch and (single) inheritance ----------------------------------------------- ### Language Syntax -- See https://flax-lang.github.io (incomplete, outdated, obsolete, etc. etc.) + +- We don't have a proper place that documents everything yet, but most of the basic stuff is probably not gonna change much. + The testing code in `build/tests/` (most of them, anyway — check `tester.flx` to see which ones we call) tests basically 90% of the + language, so that's the syntax reference for now. +- Yes, the syntax is not "officially" defined by a grammar. The reference parser implementation is the One True Definition, for now. ----------------------------------------------- @@ -64,6 +69,16 @@ Development is currently on hiatus. Work will resume NET 2019-12-09. ### Code Sample +```rust +import std::io as _ + +@entry fn main() +{ + println("hello, world!") +} + +``` + ```rust do { fn prints(m: T, a: [U: ...]) diff --git a/build/ultratiny.flx b/build/ultratiny.flx index 268a444e..67de758b 100644 --- a/build/ultratiny.flx +++ b/build/ultratiny.flx @@ -58,9 +58,10 @@ class Z: Y class A { init() { } - virtual fn foo(a: Y) -> Y + virtual fn lol(a: Y) -> &Y { - return Y(c: 471) + std::io::println("A::foo()") + return alloc Y(c: 471) } } @@ -68,21 +69,53 @@ class B : A { init() : super() { } - override fn foo(a: Y) -> Y + override fn foo(a: Y) -> &Y { - return Y(c: 748) + std::io::println("B::foo()") + return alloc Z(c: 748) + // return 3 } } +// import std::io as _ + +// @entry fn main() +// { +// println("hello, world!") +// } + +// issue #0: we basically don't really even check for overriding methods properly. // issue #1: co/contra-variance of return and parameter types for virtual methods -// issue #2: crashes when initialisers have default arguments?? +// issue #2: crashes when functions have default arguments?? // classes are a Bad Idea (tm) ): +class Tmp +{ + var z: int + + init(x: int = 3, y: int = 7) + { + this.z = x * y + } +} + + @entry fn main() { - let a = B() - let q = a.foo(Y(c: 1)).data + fn foo(x: int = 3, y: int = 7) -> int => x * y + + // let a = B() + // let q = a.foo(Y(c: 1)).data + + // let y: &X = alloc Y(c: 41) + // std::io::println("y = %", y.data) + + // let q = Tmp(k: 3, m: 7).meth() + + // let q = B().foo(Y(c: 1)).data + + let q = foo(x: 7) std::io::println("thing: %", q) } diff --git a/source/codegen/call.cpp b/source/codegen/call.cpp index 3fd41a28..b899f8fc 100644 --- a/source/codegen/call.cpp +++ b/source/codegen/call.cpp @@ -125,7 +125,7 @@ static std::vector _codegenAndArrangeFunctionCallArguments(cgn::Cod for(size_t i = 0; i < argExprs.size(); i++) { // this extra complexity is to ensure we codegen arguments from left-to-right! - auto arg = arguments[i].value; + auto arg = argExprs[i]; auto k = revArgExprs[arg]; auto infer = ft->getArgumentN(k); diff --git a/source/codegen/dotop.cpp b/source/codegen/dotop.cpp index 3e8d67de..8f136a16 100644 --- a/source/codegen/dotop.cpp +++ b/source/codegen/dotop.cpp @@ -62,6 +62,15 @@ CGResult sst::MethodDotOp::_codegen(cgn::CodegenState* cs, fir::Type* infer) fir::Type* sty = 0; auto res = getAppropriateValuePointer(cs, this, this->lhs, &sty); + if(!res->islvalue()) + { + auto tmplval = cs->irb.CreateLValue(this->lhs->type); + cs->irb.Store(res.value, tmplval); + + res.value = tmplval; + res->makeConst(); + } + // then we insert it as the first argument auto rv = util::pool(this->loc, res.value->getType()->getMutablePointerTo()); rv->rawValue = CGResult(cs->irb.AddressOf(res.value, true)); diff --git a/source/frontend/errors.cpp b/source/frontend/errors.cpp index de96e8c1..050c7a67 100644 --- a/source/frontend/errors.cpp +++ b/source/frontend/errors.cpp @@ -467,6 +467,7 @@ void OverloadError::post() + [[noreturn]] void doTheExit(bool trace) { fprintf(stderr, "there were errors, compilation cannot continue\n"); @@ -487,3 +488,8 @@ void OverloadError::post() + + + + + diff --git a/source/include/utils.h b/source/include/utils.h index 7f39a6b2..d265a6a8 100644 --- a/source/include/utils.h +++ b/source/include/utils.h @@ -171,7 +171,13 @@ namespace util template std::vector take(const std::vector& v, size_t num) { - return std::vector(v.begin(), v.begin() + num); + return std::vector(v.begin(), v.begin() + std::min(num, v.size())); + } + + template + std::vector drop(const std::vector& v, size_t num) + { + return std::vector(v.begin() + std::min(num, v.size()), v.end()); } inline std::string join(const std::vector& list, const std::string& sep) diff --git a/source/typecheck/classes.cpp b/source/typecheck/classes.cpp index 5a0c108a..48752a45 100644 --- a/source/typecheck/classes.cpp +++ b/source/typecheck/classes.cpp @@ -209,13 +209,11 @@ TCResult ast::ClassDefn::typecheck(sst::TypecheckState* fs, fir::Type* infer, co { // ok -- issue is that we cannot compare the method signatures directly -- because the method will take the 'self' of its // respective class, meaning they won't be duplicates. so, we must compare without the first parameter. - - // note: we're passing by copy here intentionally so we can erase the first one. - auto compareMethods = [&fs](std::vector a, std::vector b) -> bool { - return fs->isDuplicateOverload(a, b); + auto compareMethodSignatures = [&fs](const std::vector& a, const std::vector& b) -> bool { + return fs->isDuplicateOverload(util::drop(a, 1), util::drop(b, 1)); }; - if(bf->id.name == meth->id.name && compareMethods(bf->params, meth->params)) + if(bf->id.name == meth->id.name && compareMethodSignatures(bf->params, meth->params)) { // check for virtual functions. //* note: we don't need to care if 'bf' is the base method, because if we are 'isOverride', then we are also diff --git a/source/typecheck/dotop.cpp b/source/typecheck/dotop.cpp index df9944b7..1df3b6e7 100644 --- a/source/typecheck/dotop.cpp +++ b/source/typecheck/dotop.cpp @@ -462,8 +462,9 @@ static sst::Expr* doExpressionDotOp(sst::TypecheckState* fs, ast::DotOperator* d // ok. auto defn = fs->typeDefnMap[type]; - iceAssert(defn); + // note: if `defn` is null, then all the dcasts will fail and we'll + // fallthrough to the bottom. if(auto str = dcast(sst::StructDefn, defn)) { // right.