From 5f136447511aa308c476c4d8c404891ca66aad35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ibrahim=20Numanagi=C4=87?= Date: Sun, 5 Feb 2023 15:53:15 -0800 Subject: [PATCH 1/2] Various bug fixes (#185) * Fix #183 * Fix #162; Fix #135 * Fix #155 * Fix #191 * Fix #187 * Fix #189 * Fix vtable init; Fix failing tests on Linux * Fix #190 * Fix #156 * Fix union routing * Format --------- Co-authored-by: A. R. Shajii --- codon/parser/visitors/simplify/function.cpp | 14 +++- codon/parser/visitors/translate/translate.cpp | 5 +- codon/parser/visitors/typecheck/call.cpp | 21 ++++- codon/parser/visitors/typecheck/infer.cpp | 80 ++++++++++++------- codon/parser/visitors/typecheck/op.cpp | 41 ++++++---- codon/parser/visitors/typecheck/typecheck.cpp | 15 ++++ codon/parser/visitors/typecheck/typecheck.h | 3 + extra/python/codon/jit.pyx | 2 +- stdlib/internal/core.codon | 6 +- stdlib/internal/internal.codon | 7 +- stdlib/internal/types/intn.codon | 24 +++++- test/parser/simplify_stmt.codon | 23 ++++++ test/parser/typecheck_expr.codon | 16 ++++ test/parser/types.codon | 57 +++++++++++++ 14 files changed, 260 insertions(+), 54 deletions(-) diff --git a/codon/parser/visitors/simplify/function.cpp b/codon/parser/visitors/simplify/function.cpp index 1286bf74..f8a6ee6e 100644 --- a/codon/parser/visitors/simplify/function.cpp +++ b/codon/parser/visitors/simplify/function.cpp @@ -282,8 +282,20 @@ void SimplifyVisitor::visit(FunctionStmt *stmt) { // Expression to be used if function binding is modified by captures or decorators ExprPtr finalExpr = nullptr; // If there are captures, replace `fn` with `fn(cap1=cap1, cap2=cap2, ...)` - if (!captures.empty()) + if (!captures.empty()) { finalExpr = N(N(stmt->name), partialArgs); + // Add updated self reference in case function is recursive! + auto pa = partialArgs; + for (auto &a : pa) { + if (!a.name.empty()) + a.value = N(a.name); + else + a.value = clone(a.value); + } + f->suite = N( + N(N(rootName), N(N(rootName), pa)), + suite); + } // Parse remaining decorators for (auto i = stmt->decorators.size(); i-- > 0;) { diff --git a/codon/parser/visitors/translate/translate.cpp b/codon/parser/visitors/translate/translate.cpp index c15cc235..43be4743 100644 --- a/codon/parser/visitors/translate/translate.cpp +++ b/codon/parser/visitors/translate/translate.cpp @@ -170,7 +170,10 @@ void TranslateVisitor::visit(StringExpr *expr) { void TranslateVisitor::visit(IdExpr *expr) { auto val = ctx->find(expr->value); seqassert(val, "cannot find '{}'", expr->value); - if (auto *v = val->getVar()) + if (expr->value == "__vtable_size__") + result = make(expr, ctx->cache->classRealizationCnt + 2, + getType(expr->getType())); + else if (auto *v = val->getVar()) result = make(expr, v); else if (auto *f = val->getFunc()) result = make(expr, f); diff --git a/codon/parser/visitors/typecheck/call.cpp b/codon/parser/visitors/typecheck/call.cpp index 0cb7687b..abade182 100644 --- a/codon/parser/visitors/typecheck/call.cpp +++ b/codon/parser/visitors/typecheck/call.cpp @@ -783,16 +783,31 @@ ExprPtr TypecheckVisitor::transformHasAttr(CallExpr *expr) { .type->getStatic() ->evaluate() .getString(); - std::vector args{typ}; + std::vector> args{{"", typ}}; if (expr->expr->isId("hasattr:0")) { // Case: the first hasattr overload allows passing argument types via *args auto tup = expr->args[1].value->getTuple(); seqassert(tup, "not a tuple"); for (auto &a : tup->items) { - transformType(a); + transform(a); if (!a->getType()->getClass()) return nullptr; - args.push_back(a->getType()); + args.push_back({"", a->getType()}); + } + auto kwtup = expr->args[2].value->origExpr->getCall(); + seqassert(expr->args[2].value->origExpr && expr->args[2].value->origExpr->getCall(), + "expected call: {}", expr->args[2].value->origExpr); + auto kw = expr->args[2].value->origExpr->getCall(); + auto kwCls = + in(ctx->cache->classes, expr->args[2].value->getType()->getClass()->name); + seqassert(kwCls, "cannot find {}", + expr->args[2].value->getType()->getClass()->name); + for (size_t i = 0; i < kw->args.size(); i++) { + auto &a = kw->args[i].value; + transform(a); + if (!a->getType()->getClass()) + return nullptr; + args.push_back({kwCls->fields[i].name, a->getType()}); } } diff --git a/codon/parser/visitors/typecheck/infer.cpp b/codon/parser/visitors/typecheck/infer.cpp index 90b528ea..29ab77ef 100644 --- a/codon/parser/visitors/typecheck/infer.cpp +++ b/codon/parser/visitors/typecheck/infer.cpp @@ -382,11 +382,11 @@ StmtPtr TypecheckVisitor::prepareVTables() { // def class_init_vtables(): // return __internal__.class_make_n_vtables( + 1) auto &initAllVT = ctx->cache->functions[rep]; - auto suite = N( - N(N(N("__internal__.class_make_n_vtables:0"), - N(ctx->cache->classRealizationCnt + 1)))); + auto suite = N(N(N( + N("__internal__.class_make_n_vtables:0"), N("__vtable_size__")))); initAllVT.ast->suite = suite; auto typ = initAllVT.realizations.begin()->second->type; + LOG_REALIZE("[poly] {} : {}", typ, *suite); typ->ast = initAllVT.ast.get(); auto fx = realizeFunc(typ.get(), true); @@ -402,30 +402,36 @@ StmtPtr TypecheckVisitor::prepareVTables() { suite = N(); for (auto &[_, cls] : ctx->cache->classes) { for (auto &[r, real] : cls.realizations) { + size_t vtSz = 0; + for (auto &[base, vtable] : real->vtables) { + if (!vtable.ir) + vtSz += vtable.table.size(); + } + auto var = initFn.ast->args[0].name; + // p.__setitem__(real.ID) = Ptr[cobj](real.vtables.size() + 2) + suite->stmts.push_back(N(N( + N(N(var), "__setitem__"), N(real->id), + N(NT(NT("Ptr"), + std::vector{NT("cobj")}), + N(vtSz + 2))))); + // __internal__.class_set_typeinfo(p[real.ID], real.ID) + suite->stmts.push_back(N(N( + N("__internal__.class_set_typeinfo:0"), + N(N(var), N(real->id)), N(real->id)))); + vtSz = 0; for (auto &[base, vtable] : real->vtables) { if (!vtable.ir) { - auto var = initFn.ast->args[0].name; - // p.__setitem__(real.ID) = Ptr[cobj](real.vtables.size() + 2) - suite->stmts.push_back(N(N( - N(N(var), "__setitem__"), N(real->id), - N(NT(NT("Ptr"), - std::vector{NT("cobj")}), - N(vtable.table.size() + 2))))); - // __internal__.class_set_typeinfo(p[real.ID], real.ID) - suite->stmts.push_back(N( - N(N("__internal__.class_set_typeinfo:0"), - N(N(var), N(real->id)), - N(real->id)))); for (auto &[k, v] : vtable.table) { auto &[fn, id] = v; std::vector ids; for (auto &t : fn->getArgTypes()) ids.push_back(NT(t->realizedName())); // p[real.ID].__setitem__(f.ID, Function[](f).__raw__()) + LOG_REALIZE("[poly] vtable[{}][{}] = {}", real->id, vtSz + id, fn); suite->stmts.push_back(N(N( N(N(N(var), N(real->id)), "__setitem__"), - N(id), + N(vtSz + id), N(N( N( NT( @@ -438,12 +444,14 @@ StmtPtr TypecheckVisitor::prepareVTables() { N(fn->realizedName())), "__raw__"))))); } + vtSz += vtable.table.size(); } } } } initFn.ast->suite = suite; typ = initFn.realizations.begin()->second->type; + LOG_REALIZE("[poly] {} : {}", typ, suite->toString(2)); typ->ast = initFn.ast.get(); realizeFunc(typ.get(), true); @@ -469,6 +477,7 @@ StmtPtr TypecheckVisitor::prepareVTables() { N(N(clsTyp->realizedName()), "__vtable_id__")))); } + LOG_REALIZE("[poly] {} : {}", t, *suite); initObjFns.ast->suite = suite; t->ast = initObjFns.ast.get(); realizeFunc(t.get(), true); @@ -502,6 +511,7 @@ StmtPtr TypecheckVisitor::prepareVTables() { N(NT( NT(format("{}{}", TYPE_TUPLE, types.size())), types), "__elemsize__")); + LOG_REALIZE("[poly] {} : {}", t, *suite); initDist.ast->suite = suite; t->ast = initDist.ast.get(); realizeFunc(t.get(), true); @@ -802,8 +812,8 @@ TypecheckVisitor::generateSpecialAst(types::FuncType *type) { type->getArgTypes()[0]->getHeterogenousTuple()) { // Special case: do not realize auto-generated heterogenous __getitem__ E(Error::EXPECTED_TYPE, getSrcInfo(), "iterable"); - } else if (startswith(ast->name, "Function.__call__")) { - // Special case: Function.__call__ + } else if (startswith(ast->name, "Function.__call_internal__")) { + // Special case: Function.__call_internal__ /// TODO: move to IR one day std::vector items; items.push_back(nullptr); @@ -826,6 +836,14 @@ TypecheckVisitor::generateSpecialAst(types::FuncType *type) { ll.push_back(format("ret {{}} %{}", as.size())); items[0] = N(N(combine2(ll, "\n"))); ast->suite = N(items); + } else if (startswith(ast->name, "Union.__new__:0")) { + auto unionType = type->funcParent->getUnion(); + seqassert(unionType, "expected union, got {}", type->funcParent); + + StmtPtr suite = N(N( + N("__internal__.new_union:0"), N(type->ast->args[0].name), + N(unionType->realizedTypeName()))); + ast->suite = suite; } else if (startswith(ast->name, "__internal__.new_union:0")) { // Special case: __internal__.new_union // def __internal__.new_union(value, U[T0, ..., TN]): @@ -910,21 +928,29 @@ TypecheckVisitor::generateSpecialAst(types::FuncType *type) { auto suite = N(); int tag = 0; for (auto &t : unionTypes) { + auto callee = + N(N(N("__internal__.union_get_data:0"), + N(selfVar), NT(t->realizedName())), + fnName); + auto args = N(N(ast->args[2].name.substr(1))); + auto kwargs = N(N(ast->args[3].name.substr(2))); + std::vector callArgs; + ExprPtr check = + N(N("hasattr"), NT(t->realizedName()), + N(fnName), args->clone(), kwargs->clone()); suite->stmts.push_back(N( - N(N(N("__internal__.union_get_tag:0"), - N(selfVar)), - "==", N(tag)), - N(N( - N(N(N("__internal__.union_get_data:0"), - N(selfVar), NT(t->realizedName())), - fnName), - N(N(ast->args[2].name.substr(1))), - N(N(ast->args[3].name.substr(2))))))); + N( + check, "&&", + N(N(N("__internal__.union_get_tag:0"), + N(selfVar)), + "==", N(tag))), + N(N(N(callee, args, kwargs))))); tag++; } suite->stmts.push_back( N(N(N("std.internal.types.error.TypeError"), N("invalid union call")))); + // suite->stmts.push_back(N(N())); unify(type->getRetType(), ctx->instantiate(ctx->getType("Union"))); ast->suite = suite; } else if (startswith(ast->name, "__internal__.get_union_first:0")) { diff --git a/codon/parser/visitors/typecheck/op.cpp b/codon/parser/visitors/typecheck/op.cpp index b6551acd..b39553e1 100644 --- a/codon/parser/visitors/typecheck/op.cpp +++ b/codon/parser/visitors/typecheck/op.cpp @@ -657,8 +657,12 @@ ExprPtr TypecheckVisitor::transformBinaryMagic(BinaryExpr *expr) { if (!lt->is("pyobj") && rt->is("pyobj")) { // Special case: `obj op pyobj` -> `rhs.__rmagic__(lhs)` on lhs // Assumes that pyobj implements all left and right magics - return transform(N(N(expr->rexpr, format("__{}__", rightMagic)), - expr->lexpr)); + auto l = ctx->cache->getTemporaryVar("l"), r = ctx->cache->getTemporaryVar("r"); + return transform( + N(N(N(l), expr->lexpr), + N(N(r), expr->rexpr), + N(N(N(r), format("__{}__", rightMagic)), + N(l)))); } if (lt->getUnion()) { // Special case: `union op obj` -> `union.__magic__(rhs)` @@ -667,19 +671,24 @@ ExprPtr TypecheckVisitor::transformBinaryMagic(BinaryExpr *expr) { } // Normal operations: check if `lhs.__magic__(lhs, rhs)` exists - auto method = findBestMethod(lt, format("__{}__", magic), {expr->lexpr, expr->rexpr}); - - // Right-side magics: check if `rhs.__rmagic__(rhs, lhs)` exists - if (!method && (method = findBestMethod(rt, format("__{}__", rightMagic), - {expr->rexpr, expr->lexpr}))) { - swap(expr->lexpr, expr->rexpr); - } - - if (method) { + if (auto method = + findBestMethod(lt, format("__{}__", magic), {expr->lexpr, expr->rexpr})) { // Normal case: `__magic__(lhs, rhs)` return transform( N(N(method->ast->name), expr->lexpr, expr->rexpr)); } + + // Right-side magics: check if `rhs.__rmagic__(rhs, lhs)` exists + if (auto method = findBestMethod(rt, format("__{}__", rightMagic), + {expr->rexpr, expr->lexpr})) { + auto l = ctx->cache->getTemporaryVar("l"), r = ctx->cache->getTemporaryVar("r"); + return transform(N( + N(N(l), expr->lexpr), + N(N(r), expr->rexpr), + N(N(method->ast->name), N(r), N(l)))); + } + // 145 + return nullptr; } @@ -745,14 +754,18 @@ TypecheckVisitor::transformStaticTupleIndex(const ClassTypePtr &tuple, sliceAdjustIndices(sz, &start, &stop, step); // Generate a sub-tuple + auto var = N(ctx->cache->getTemporaryVar("tup")); + auto ass = N(var, expr); std::vector te; for (auto i = start; (step > 0) ? (i < stop) : (i > stop); i += step) { if (i < 0 || i >= sz) E(Error::TUPLE_RANGE_BOUNDS, index, sz - 1, i); - te.push_back(N(clone(expr), classItem->fields[i].name)); + te.push_back(N(clone(var), classItem->fields[i].name)); } - return {true, transform(N( - N(format(TYPE_TUPLE "{}", te.size()), "__new__"), te))}; + ExprPtr e = transform(N( + std::vector{ass}, + N(N(format(TYPE_TUPLE "{}", te.size()), "__new__"), te))); + return {true, e}; } return {false, nullptr}; diff --git a/codon/parser/visitors/typecheck/typecheck.cpp b/codon/parser/visitors/typecheck/typecheck.cpp index 4d0d4ec4..7f1131d2 100644 --- a/codon/parser/visitors/typecheck/typecheck.cpp +++ b/codon/parser/visitors/typecheck/typecheck.cpp @@ -200,6 +200,21 @@ types::FuncTypePtr TypecheckVisitor::findBestMethod(const ClassTypePtr &typ, return m.empty() ? nullptr : m[0]; } +/// Select the best method indicated of an object that matches the given argument +/// types. See @c findMatchingMethods for details. +types::FuncTypePtr TypecheckVisitor::findBestMethod( + const ClassTypePtr &typ, const std::string &member, + const std::vector> &args) { + std::vector callArgs; + for (auto &[n, a] : args) { + callArgs.push_back({n, std::make_shared()}); // dummy expression + callArgs.back().value->setType(a); + } + auto methods = ctx->findMethod(typ->name, member, false); + auto m = findMatchingMethods(typ, methods, callArgs); + return m.empty() ? nullptr : m[0]; +} + /// Select the best method among the provided methods given the list of arguments. /// See @c reorderNamedArgs for details. std::vector diff --git a/codon/parser/visitors/typecheck/typecheck.h b/codon/parser/visitors/typecheck/typecheck.h index 4fb73a77..8b07c196 100644 --- a/codon/parser/visitors/typecheck/typecheck.h +++ b/codon/parser/visitors/typecheck/typecheck.h @@ -210,6 +210,9 @@ private: types::FuncTypePtr findBestMethod(const types::ClassTypePtr &typ, const std::string &member, const std::vector &args); + types::FuncTypePtr + findBestMethod(const types::ClassTypePtr &typ, const std::string &member, + const std::vector> &args); std::vector findMatchingMethods(const types::ClassTypePtr &typ, const std::vector &methods, diff --git a/extra/python/codon/jit.pyx b/extra/python/codon/jit.pyx index 0da9be63..e62fca34 100644 --- a/extra/python/codon/jit.pyx +++ b/extra/python/codon/jit.pyx @@ -3,7 +3,7 @@ # distutils: language=c++ # cython: language_level=3 # cython: c_string_type=unicode -# cython: c_string_encoding=ascii +# cython: c_string_encoding=utf8 from libcpp.string cimport string from libcpp.vector cimport vector diff --git a/stdlib/internal/core.codon b/stdlib/internal/core.codon index d8525436..d2927cc4 100644 --- a/stdlib/internal/core.codon +++ b/stdlib/internal/core.codon @@ -108,7 +108,9 @@ class Ref[T]: @__internal__ @tuple class Union[TU]: - pass + # compiler-generated + def __new__(val): + TU # dummy @__internal__ @@ -153,7 +155,7 @@ def isinstance(obj, what): def overload(): pass -def hasattr(obj, attr: Static[str], *args): +def hasattr(obj, attr: Static[str], *args, **kwargs): """Special handling""" pass diff --git a/stdlib/internal/internal.codon b/stdlib/internal/internal.codon index 9a827040..36fd0802 100644 --- a/stdlib/internal/internal.codon +++ b/stdlib/internal/internal.codon @@ -11,6 +11,8 @@ from C import seq_print(str) from C import exit(int) from C import malloc(int) -> cobj as c_malloc +__vtable_size__ = 0 + @extend class __internal__: @pure @@ -438,8 +440,11 @@ class Function: return __internal__.raw_type_str(self.__raw__(), "function") @llvm - def __call__(self, *args) -> TR: + def __call_internal__(self: Function[T, TR], args: T) -> TR: noop # compiler will populate this one + def __call__(self, *args) -> TR: + return Function.__call_internal__(self, args) + __vtables__ = __internal__.class_init_vtables() def _____(): __vtables__ # make it global! diff --git a/stdlib/internal/types/intn.codon b/stdlib/internal/types/intn.codon index 450a0dda..2973f025 100644 --- a/stdlib/internal/types/intn.codon +++ b/stdlib/internal/types/intn.codon @@ -119,9 +119,13 @@ class Int: @pure @llvm - def __floordiv__(self, other: Int[N]) -> Int[N]: + def _floordiv(self, other: Int[N]) -> Int[N]: %0 = sdiv i{=N} %self, %other ret i{=N} %0 + def __floordiv__(self, other: Int[N]) -> Int[N]: + if N > 128: + compile_error("division is not supported on Int[N] when N > 128") + return self._floordiv(other) @pure @llvm @@ -133,9 +137,13 @@ class Int: @pure @llvm - def __mod__(self, other: Int[N]) -> Int[N]: + def _mod(self, other: Int[N]) -> Int[N]: %0 = srem i{=N} %self, %other ret i{=N} %0 + def __mod__(self, other: Int[N]) -> Int[N]: + if N > 128: + compile_error("modulus is not supported on Int[N] when N > 128") + return self._mod(other) def __divmod__(self, other: Int[N]) -> Tuple[Int[N], Int[N]]: d = self // other @@ -344,9 +352,13 @@ class UInt: @pure @llvm - def __floordiv__(self, other: UInt[N]) -> UInt[N]: + def _floordiv(self, other: UInt[N]) -> UInt[N]: %0 = udiv i{=N} %self, %other ret i{=N} %0 + def __floordiv__(self, other: UInt[N]) -> UInt[N]: + if N > 128: + compile_error("division is not supported on UInt[N] when N > 128") + return self._floordiv(other) @pure @llvm @@ -358,9 +370,13 @@ class UInt: @pure @llvm - def __mod__(self, other: UInt[N]) -> UInt[N]: + def _mod(self, other: UInt[N]) -> UInt[N]: %0 = urem i{=N} %self, %other ret i{=N} %0 + def __mod__(self, other: UInt[N]) -> UInt[N]: + if N > 128: + compile_error("modulus is not supported on UInt[N] when N > 128") + return self._mod(other) def __divmod__(self, other: UInt[N]) -> Tuple[UInt[N], UInt[N]]: return (self // other, self % other) diff --git a/test/parser/simplify_stmt.codon b/test/parser/simplify_stmt.codon index faeabbfa..3d8a9541 100644 --- a/test/parser/simplify_stmt.codon +++ b/test/parser/simplify_stmt.codon @@ -806,6 +806,18 @@ print X(1) + Y(2) #: 5 print Y(1) + X(2) #: 4 +class A: + def __radd__(self, n: int): + return 0 +def f(): + print('f') + return 1 +def g(): + print('g') + return A() +f() + g() +#: f +#: g #%% magic_2,barebones @tuple @@ -1232,3 +1244,14 @@ def foo(): foo() #! name 'x' is not defined #! name 'b' is not defined + +#%% capture_recursive,barebones +def f(x: int) -> int: + z = 2 * x + def g(y: int) -> int: + if y == 0: + return 1 + else: + return g(y - 1) * z + return g(4) +print(f(3)) #: 1296 diff --git a/test/parser/typecheck_expr.codon b/test/parser/typecheck_expr.codon index 5916a53d..4b1da720 100644 --- a/test/parser/typecheck_expr.codon +++ b/test/parser/typecheck_expr.codon @@ -208,6 +208,22 @@ print a[1] #: 2s print a[0:2], a[:2], a[1:] #: (1, '2s') (1, '2s') ('2s', 3.3) print a[0:3:2], a[-1:] #: (1, 3.3) (3.3) +#%% static_index_side,barebones +def foo(a): + print(a) + return a + +print (foo(2), foo(1))[::-1] +#: 2 +#: 1 +#: (1, 2) +print (foo(1), foo(2), foo(3), foo(4))[2] +#: 1 +#: 2 +#: 3 +#: 4 +#: 3 + #%% static_index_lenient,barebones a = (1, 2) print a[3:5] #: () diff --git a/test/parser/types.codon b/test/parser/types.codon index 8319646a..a9aa9228 100644 --- a/test/parser/types.codon +++ b/test/parser/types.codon @@ -1477,6 +1477,20 @@ x : Union[A,B,C] = A() print x.foo(), x.foo().__class__.__name__ #: 1 Union[List[bool],int,str] +xx = Union[int, str](0) +print(xx) #: 0 + +#%% union_error,barebones +a: Union[int, str] = 123 +print(123 == a) #: True +print(a == 123) #: True +try: + a = "foo" + print(a == 123) +except TypeError: + print("oops", a) #: oops 'foo' + + #%% generator_capture_nonglobal,barebones # Issue #49 def foo(iter): @@ -1775,3 +1789,46 @@ class Div(BinOp): expr : Expr = Mul(Const(3), Add(Const(10), Const(5))) print(expr.eval()) #: 45 + +#%% polymorphism_4 +class A(object): + a: int + def __init__(self, a: int): + self.a = a + + def test_a(self, n: int): + print("test_a:A", n) + + def test(self, n: int): + print("test:A", n) + + def test2(self, n: int): + print("test2:A", n) + +class B(A): + b: int + def __init__(self, a: int, b: int): + super().__init__(a) + self.b = b + + def test(self, n: int): + print("test:B", n) + + def test2(self, n: int): + print("test2:B", n) + +class C(B): + pass + +b = B(1, 2) +b.test_a(1) +b.test(1) +#: test_a:A 1 +#: test:B 1 + +a: A = b +a.test(1) +a.test2(2) +#: test:B 1 +#: test2:B 2 + From ab7387b66a7be8b1cedafc6aec10b0b402d769ff Mon Sep 17 00:00:00 2001 From: "A. R. Shajii" Date: Sun, 5 Feb 2023 19:05:30 -0500 Subject: [PATCH 2/2] Bump version --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index da3f0243..0a06e6f1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,10 +1,10 @@ cmake_minimum_required(VERSION 3.14) project( Codon - VERSION "0.15.4" + VERSION "0.15.5" HOMEPAGE_URL "https://github.com/exaloop/codon" DESCRIPTION "high-performance, extensible Python compiler") -set(CODON_JIT_PYTHON_VERSION "0.1.2") +set(CODON_JIT_PYTHON_VERSION "0.1.3") configure_file("${PROJECT_SOURCE_DIR}/cmake/config.h.in" "${PROJECT_SOURCE_DIR}/codon/config/config.h") configure_file("${PROJECT_SOURCE_DIR}/cmake/config.py.in"