Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
107 commits
Select commit Hold shift + click to select a range
247e0ac
Add initial unicode type
arshajii Aug 4, 2026
a873700
Additional formatting support
arshajii Aug 4, 2026
c4a0637
Expand formatting
arshajii Aug 5, 2026
43af1a4
Add more tests
arshajii Aug 5, 2026
60b0b83
Add new-style formatting
arshajii Aug 6, 2026
5def26b
More tests
arshajii Aug 6, 2026
20fbd93
Expand unicode functionality
arshajii Aug 8, 2026
33cf56a
Optimize string search
arshajii Aug 9, 2026
8458858
Fix tests
arshajii Aug 9, 2026
1e3e7ca
Cleanup
arshajii Aug 9, 2026
60ddbcc
Add kind-specific string search functions
arshajii Aug 9, 2026
7c6c84f
Update unicode type layout
arshajii Aug 9, 2026
d5c90a3
Remove unused specialization
arshajii Aug 10, 2026
5ecdbca
More tests
arshajii Aug 10, 2026
95e375a
Fix rpartition
arshajii Aug 10, 2026
10a306f
Update unicode hash
arshajii Aug 10, 2026
29f11da
Optimize unicode translation
arshajii Aug 11, 2026
b147af0
Optimize unicode replacement
arshajii Aug 11, 2026
08b76aa
Use vectorized string search
arshajii Aug 11, 2026
d3bd7a8
Add copy magic methods
arshajii Aug 12, 2026
f3fa69e
Refactor and integrate unicode implementation
arshajii Aug 17, 2026
bb29bc3
Fix tests
arshajii Aug 17, 2026
3081c1d
Update bytes API
arshajii Aug 17, 2026
eefa3df
Add bytes.decode()
arshajii Aug 17, 2026
b36f89b
Update re module to work with unicode
arshajii Aug 18, 2026
331827e
Update file
arshajii Aug 19, 2026
4081a2c
Fail if core/stdlib typechecking fails
inumanag Aug 20, 2026
48ec4fc
Fix string codegen
arshajii Aug 20, 2026
bc35294
Fix int parsing
arshajii Aug 20, 2026
0c71161
Expand file APIs
arshajii Aug 20, 2026
804a79d
Update file APIs
arshajii Aug 21, 2026
cb72acb
Optimize file operations
arshajii Aug 21, 2026
c392ec3
Optimize file I/O
arshajii Aug 21, 2026
336ea5d
Add IR bytes constant
arshajii Aug 21, 2026
9cfa08b
Fix print
arshajii Aug 21, 2026
9cef836
Update Python interop for unicode strings
arshajii Aug 21, 2026
901a6c5
Update GPU conversions for unicode strings
arshajii Aug 21, 2026
34bb746
Update exception runtime library code for unicode
arshajii Aug 21, 2026
f758c47
b'' string support; Literal[str] utf-8 support
inumanag Aug 22, 2026
df7859b
b'' string support
inumanag Aug 22, 2026
68ad0d3
Fix b'' support; add b'' correctness checking and use IR type
inumanag Aug 23, 2026
ee7487c
Support locale-aware formatting
arshajii Aug 23, 2026
321d060
Fix format code
arshajii Aug 24, 2026
bada0c3
Fix tests
arshajii Aug 24, 2026
bd359a8
Remove legacy formatting code
arshajii Aug 24, 2026
d34c42d
Add more tests
arshajii Aug 24, 2026
0f2c5b4
Support bytes formatting
arshajii Aug 24, 2026
6c66ac7
Add formatting optimization IR pass
arshajii Aug 25, 2026
135d123
Add tests
arshajii Aug 26, 2026
721376a
Use str.format for f-strings; Fix x= printing; Fix f-string parsing
inumanag Aug 26, 2026
89f775a
Update str usage in stdlib
arshajii Aug 26, 2026
8ce44d8
Fix stdlib str usage
arshajii Aug 26, 2026
acf2b53
Fix formatting and f-strings
arshajii Aug 27, 2026
24c69ee
Minor f-string fixes
inumanag Aug 28, 2026
4795104
Fix tests
arshajii Aug 28, 2026
278aac7
Fix f-strings
arshajii Aug 28, 2026
3cb4f3a
Fix tests
arshajii Aug 28, 2026
de1d71c
Fix test
arshajii Aug 28, 2026
f677763
Fix formatting
arshajii Aug 28, 2026
7a45de5
Fix tests
arshajii Aug 28, 2026
19d194b
Fix tests
arshajii Aug 28, 2026
7c5eb70
Fix tests
arshajii Aug 28, 2026
4d99c6e
Refactor unicode auto-generated files
arshajii Aug 29, 2026
bb0195e
Update docs
arshajii Aug 29, 2026
d36b66e
Add bytearray
arshajii Aug 29, 2026
bebce0b
Optimize bytearray
arshajii Aug 29, 2026
6fc28eb
Fix Union.__repr__
inumanag Aug 30, 2026
f4790e7
Update docs
arshajii Aug 30, 2026
e5b9e4b
Remove can_call guard
arshajii Aug 30, 2026
3da7cfa
Uniuon.__format__
inumanag Aug 30, 2026
2f3c480
Merge branch 'unicode' of github.com:exaloop/codon into unicode
inumanag Aug 30, 2026
c6cdf43
Fix union formatting
arshajii Aug 30, 2026
4aca286
Fix CMake
arshajii Aug 30, 2026
9e7611c
Fix file default arguments
arshajii Aug 30, 2026
716b339
Fix incompatibilities
arshajii Aug 30, 2026
56c7106
Fix tests
arshajii Aug 31, 2026
14f6c45
Update file APIs
arshajii Aug 31, 2026
7271ebd
Fix pyext test
arshajii Aug 31, 2026
91e939f
Fix tests
arshajii Aug 31, 2026
c9f2c9a
File and str optimizations
arshajii Aug 31, 2026
9853ed7
clang-format
arshajii Aug 31, 2026
7a6b0c6
Fix allocation hoister
arshajii Aug 31, 2026
b2ae411
Optimize file
arshajii Sep 1, 2026
a4c1f08
File optimizations and more tests
arshajii Sep 1, 2026
c75a0e9
More optimizations
arshajii Sep 3, 2026
7457562
Fix file newline semantics
arshajii Sep 3, 2026
0e55379
Fix LLVM codegen
arshajii Sep 3, 2026
878e2da
Fix LLVM codegen
arshajii Sep 3, 2026
9e7256f
Move unicodedata import to improve parse time
arshajii Sep 4, 2026
f7bdd6a
Optimize grammar
inumanag Sep 4, 2026
34dc6b6
Add missing bytes and bytearray methods
arshajii Sep 4, 2026
98089a3
Optimize string search
arshajii Sep 4, 2026
98f545f
Optimize encode and decode
arshajii Sep 4, 2026
c4644d0
Optimize formatting
arshajii Sep 4, 2026
f5ff8d5
Fix buffer management
arshajii Sep 5, 2026
eab0998
Final file fixes
arshajii Sep 5, 2026
77cf0da
More str optimizations
arshajii Sep 5, 2026
5c39784
Fix asyncio potential deadlock
arshajii Sep 5, 2026
b53568d
More str optimizations
arshajii Sep 5, 2026
eaf04b2
More str optimizations
arshajii Sep 6, 2026
d611246
More str optimizations
arshajii Sep 6, 2026
eece2ce
Misc fixes
arshajii Sep 7, 2026
67f3804
Bump version
arshajii Sep 7, 2026
d3f5d0a
Optimize isalpha(), isdigit()
arshajii Sep 7, 2026
351f68c
Performance fixes
inumanag Sep 7, 2026
1dff445
Merge branch 'unicode' of https://github.com/exaloop/codon into unicode
arshajii Sep 7, 2026
96859d3
Merge branch 'develop' into unicode
arshajii Sep 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-return-type")
endif()
set(CMAKE_CXX_FLAGS_DEBUG "-g")
set(CMAKE_CXX_FLAGS_DEBUG "-O1 -g")
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-limit-debug-info")
endif()
Expand Down
16 changes: 10 additions & 6 deletions codon/parser/ast/stmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -333,12 +333,14 @@ std::string GlobalStmt::toString(int indent) const {
FunctionStmt::FunctionStmt(std::string name, Expr *ret, std::vector<Param> args,
Stmt *suite, std::vector<Expr *> decorators, bool async)
: AcceptorExtend(), Items(std::move(args)), name(std::move(name)), ret(ret),
suite(SuiteStmt::wrap(suite)), decorators(std::move(decorators)), async(async) {}
suite(SuiteStmt::wrap(suite)), decorators(std::move(decorators)), async(async),
nonInferrableGenerics(nullptr) {}
FunctionStmt::FunctionStmt(const FunctionStmt &stmt, bool clean)
: AcceptorExtend(stmt, clean), Items(ast::clone(stmt.items, clean)),
name(stmt.name), ret(ast::clone(stmt.ret, clean)),
suite(ast::clone(stmt.suite, clean)),
decorators(ast::clone(stmt.decorators, clean)), async(stmt.async) {}
decorators(ast::clone(stmt.decorators, clean)), async(stmt.async),
nonInferrableGenerics(nullptr) {}
std::string FunctionStmt::toString(int indent) const {
std::string pad = indent > 0 ? ("\n" + std::string(indent + INDENT_SIZE, ' ')) : " ";
std::vector<std::string> as;
Expand Down Expand Up @@ -431,8 +433,10 @@ class IdSearchVisitor : public CallbackASTVisitor<bool, bool> {

/// Check if a function can be called with the given arguments.
/// See @c reorderNamedArgs for details.
std::unordered_set<std::string> FunctionStmt::getNonInferrableGenerics() const {
std::unordered_set<std::string> nonInferrableGenerics;
const std::unordered_set<std::string> &FunctionStmt::getNonInferrableGenerics() {
if (nonInferrableGenerics)
return *nonInferrableGenerics;
nonInferrableGenerics = std::make_shared<std::unordered_set<std::string>>();
for (const auto &a : items) {
if (a.status == Param::Generic && !a.defaultValue) {
bool inferrable = false;
Expand All @@ -444,10 +448,10 @@ std::unordered_set<std::string> FunctionStmt::getNonInferrableGenerics() const {
if (ret && IdSearchVisitor(a.name).transform(ret))
inferrable = true;
if (!inferrable)
nonInferrableGenerics.insert(a.name);
nonInferrableGenerics->insert(a.name);
}
}
return nonInferrableGenerics;
return *nonInferrableGenerics;
}

ClassStmt::ClassStmt(std::string name, std::vector<Param> args, Stmt *suite,
Expand Down
12 changes: 10 additions & 2 deletions codon/parser/ast/stmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#pragma once

#include <memory>
#include <optional>
#include <ostream>
#include <string>
#include <vector>
Expand Down Expand Up @@ -500,7 +501,11 @@ struct FunctionStmt : public AcceptorExtend<FunctionStmt, Stmt>, Items<Param> {
void setDecorators(const std::vector<Expr *> &d) { decorators = d; }
bool isAsync() const { return async; }
void setAsync() { async = true; }
void addParam(const Param &p) { items.push_back(p); }
void addParam(const Param &p) {
items.push_back(p);
if (nonInferrableGenerics)
nonInferrableGenerics->clear();
}

/// @return a function signature that consists of generics and arguments in a
/// S-expression form.
Expand All @@ -509,7 +514,7 @@ struct FunctionStmt : public AcceptorExtend<FunctionStmt, Stmt>, Items<Param> {
size_t getStarArgs() const;
size_t getKwStarArgs() const;
std::string getDocstr() const;
std::unordered_set<std::string> getNonInferrableGenerics() const;
const std::unordered_set<std::string> &getNonInferrableGenerics();
bool hasFunctionAttribute(const std::string &attr) const;

ACCEPT(FunctionStmt, ASTVisitor, name, items, ret, suite, decorators, async);
Expand All @@ -522,6 +527,9 @@ struct FunctionStmt : public AcceptorExtend<FunctionStmt, Stmt>, Items<Param> {
bool async;
std::string signature;

// Cache non-inferrable generics for speed.
std::shared_ptr<std::unordered_set<std::string>> nonInferrableGenerics;

friend struct Cache;
};

Expand Down
8 changes: 6 additions & 2 deletions codon/parser/ast/types/class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,13 @@ int ClassType::unify(Type *typ, Unification *us) {

TypePtr ClassType::generalize(int atLevel) const {
std::vector<Generic> g, hg;
g.reserve(generics.size());
hg.reserve(hiddenGenerics.size());
for (auto &t : generics)
g.push_back(t.generalize(atLevel));
for (auto &t : hiddenGenerics)
hg.push_back(t.generalize(atLevel));
auto c = std::make_shared<ClassType>(cache, name, g, hg);
auto c = std::make_shared<ClassType>(cache, name, std::move(g), std::move(hg));
c->isTuple = isTuple;
c->setSrcInfo(getSrcInfo());
return c;
Expand All @@ -166,11 +168,13 @@ TypePtr ClassType::generalize(int atLevel) const {
TypePtr ClassType::instantiate(int atLevel, int *unboundCount,
std::unordered_map<int, TypePtr> *cache) const {
std::vector<Generic> g, hg;
g.reserve(generics.size());
hg.reserve(hiddenGenerics.size());
for (auto &t : generics)
g.push_back(t.instantiate(atLevel, unboundCount, cache));
for (auto &t : hiddenGenerics)
hg.push_back(t.instantiate(atLevel, unboundCount, cache));
auto c = std::make_shared<ClassType>(this->cache, name, g, hg);
auto c = std::make_shared<ClassType>(this->cache, name, std::move(g), std::move(hg));
c->isTuple = isTuple;
c->setSrcInfo(getSrcInfo());
return c;
Expand Down
13 changes: 11 additions & 2 deletions codon/parser/ast/types/function.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ FuncType::FuncType(const ClassType *baseType, FunctionStmt *ast,
: ClassType(baseType), ast(ast), funcGenerics(std::move(funcGenerics)),
funcParent(std::move(funcParent)) {}

// Instantiation/generalization produce a private temporary base. Take its storage
// instead of copying its generic names and shared pointers into the function type.
FuncType::FuncType(ClassType &&baseType, FunctionStmt *ast,
std::vector<Generic> funcGenerics, TypePtr funcParent)
: ClassType(std::move(baseType)), ast(ast), funcGenerics(std::move(funcGenerics)),
funcParent(std::move(funcParent)) {}

int FuncType::unify(Type *typ, Unification *us) {
if (this == typ)
return 0;
Expand Down Expand Up @@ -43,18 +50,20 @@ int FuncType::unify(Type *typ, Unification *us) {

TypePtr FuncType::generalize(int atLevel) const {
std::vector<Generic> fg;
fg.reserve(funcGenerics.size());
for (auto &t : funcGenerics)
fg.push_back(t.generalize(atLevel));
auto p = funcParent ? funcParent->generalize(atLevel) : nullptr;

auto r = std::static_pointer_cast<ClassType>(this->ClassType::generalize(atLevel));
auto t = std::make_shared<FuncType>(r->getClass(), ast, fg, p);
auto t = std::make_shared<FuncType>(std::move(*r), ast, std::move(fg), std::move(p));
return t;
}

TypePtr FuncType::instantiate(int atLevel, int *unboundCount,
std::unordered_map<int, TypePtr> *cache) const {
std::vector<Generic> fg;
fg.reserve(funcGenerics.size());
for (auto &t : funcGenerics) {
fg.push_back(t.instantiate(atLevel, unboundCount, cache));
if (cache && fg.back().type) {
Expand All @@ -65,7 +74,7 @@ TypePtr FuncType::instantiate(int atLevel, int *unboundCount,
auto p = funcParent ? funcParent->instantiate(atLevel, unboundCount, cache) : nullptr;
auto r = std::static_pointer_cast<ClassType>(
this->ClassType::instantiate(atLevel, unboundCount, cache));
auto t = std::make_shared<FuncType>(r->getClass(), ast, fg, p);
auto t = std::make_shared<FuncType>(std::move(*r), ast, std::move(fg), std::move(p));
return t;
}

Expand Down
2 changes: 2 additions & 0 deletions codon/parser/ast/types/function.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ struct FuncType : public ClassType {
const ClassType *baseType, FunctionStmt *ast,
std::vector<ClassType::Generic> funcGenerics = std::vector<ClassType::Generic>(),
TypePtr funcParent = nullptr);
FuncType(ClassType &&baseType, FunctionStmt *ast,
std::vector<ClassType::Generic> funcGenerics, TypePtr funcParent);

public:
int unify(Type *typ, Unification *undo) override;
Expand Down
2 changes: 1 addition & 1 deletion codon/parser/visitors/typecheck/call.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -725,7 +725,7 @@ Expr *TypecheckVisitor::callReorderArguments(FuncType *calleeFn, CallExpr *expr,
typeArgs.size() == calleeFn->funcGenerics.size()),
"bad vector sizes");
if (!calleeFn->funcGenerics.empty()) {
auto niGenerics = calleeFn->ast->getNonInferrableGenerics();
const auto &niGenerics = calleeFn->ast->getNonInferrableGenerics();
for (size_t si = 0; !expr->hasAttribute(Attr::ExprOrderedCall) &&
si < calleeFn->funcGenerics.size();
si++) {
Expand Down
14 changes: 8 additions & 6 deletions codon/parser/visitors/typecheck/typecheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ int TypecheckVisitor::canCall(types::FuncType *fn, const std::vector<CallArg> &a
}

std::vector<std::pair<types::Type *, size_t>> reordered;
auto niGenerics = fn->ast->getNonInferrableGenerics();
const auto &niGenerics = fn->ast->getNonInferrableGenerics();
auto score = reorderNamedArgs(
fn, args,
[&](int s, int k, const std::vector<std::vector<int>> &slots, bool _) {
Expand Down Expand Up @@ -611,8 +611,9 @@ TypecheckVisitor::canWrapExpr(Type *exprType, Type *expectedType, FuncType *call
bool allowUnwrap, bool isEllipsis) {
auto expectedClass = expectedType->getClass();
auto exprClass = exprType->getClass();
auto doArgWrap = !callee || !callee->ast->hasFunctionAttribute(getMangledFunc(
"std.internal.attributes", "no_argument_wrap"));
static const auto noArgumentWrap =
getMangledFunc("std.internal.attributes", "no_argument_wrap");
auto doArgWrap = !callee || !callee->ast->hasFunctionAttribute(noArgumentWrap);
if (!doArgWrap)
return {true, expectedType ? expectedType->shared_from_this() : nullptr, nullptr};

Expand Down Expand Up @@ -1019,10 +1020,11 @@ TypecheckVisitor::extractNamedTuple(Expr *expr) {

std::vector<Cache::Class::ClassField>
TypecheckVisitor::getClassFields(types::ClassType *t) const {
auto f = getClass(t->name)->fields;
// Tuple has MAX_TUPLE fields; copy only the requested prefix, not the whole table.
const auto &f = getClass(t->name)->fields;
if (t->is(TYPE_TUPLE))
f = std::vector<Cache::Class::ClassField>(f.begin(),
f.begin() + t->generics.size());
return std::vector<Cache::Class::ClassField>(f.begin(),
f.begin() + t->generics.size());
return f;
}

Expand Down
Loading