diff --git a/library/browser/html.hexa b/library/browser/html.hexa
index 293e31c..8b1a803 100644
--- a/library/browser/html.hexa
+++ b/library/browser/html.hexa
@@ -1,6 +1,6 @@
// The MIT License
//
-// Copyright (C) 2021-2023 Oleh Petrenko
+// Copyright (C) 2021-2024 Oleh Petrenko
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -20,6 +20,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
+/// Global browser functions and values
declare let window: {
/// Raw global window object
window: Any
diff --git a/library/c/runtime.hexa b/library/c/runtime.hexa
index 07ff098..21b62ea 100644
--- a/library/c/runtime.hexa
+++ b/library/c/runtime.hexa
@@ -1,6 +1,6 @@
// The MIT License
//
-// Copyright (C) 2022 Oleh Petrenko
+// Copyright (C) 2022-2024 Oleh Petrenko
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -26,9 +26,10 @@
fun
hexaRuntimeInit(): Void
{
-
+ // TODO
}
+// TODO description and documentation
@struct class RuntimeAllocated {
}
diff --git a/library/c/string.hexa b/library/c/string.hexa
index 39f88ee..e576699 100644
--- a/library/c/string.hexa
+++ b/library/c/string.hexa
@@ -154,7 +154,7 @@ class String {
}
static fun fromUTF8z(string: ConstArrayPointer): String {
- // Note: must use own string length implementation cause incompatible with freestanding targets
+ // NOTE must use own string length implementation cause incompatible with freestanding targets
let size: Int = countUTF8z(string)
// TODO test type check that constructor is private
// TODO use stack allocated array for small strings or .bss 64k one if size < 64k
@@ -307,7 +307,7 @@ class String {
static fun fromInt32(value: Int): String {
// TODO just [0, ..., 0] N times
- // Note: reserves 2 bytes for null-terminator
+ // NOTE reserves 2 bytes for null-terminator
// ^ for some reason required despite being UInt16-array
// TODO ^ test it more, comment/overwrite `bytes[i] = 0` etc
var bytes: ArrayByValue = [0]
diff --git a/library/nodejs/nodejs.hexa b/library/nodejs/nodejs.hexa
index 267fbd0..97c6314 100644
--- a/library/nodejs/nodejs.hexa
+++ b/library/nodejs/nodejs.hexa
@@ -1,6 +1,6 @@
// The MIT License
//
-// Copyright (C) 2021-2023 Oleh Petrenko
+// Copyright (C) 2021-2024 Oleh Petrenko
// Copyright (C) 2018 Bogdan Danylchenko
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -25,7 +25,7 @@ declare fun require(package: String): Any
declare let __dirname: String
declare let __filename: String
-// TODO reqire(Buffer)?
+// TODO reqire(Buffer)? node:Buffer `require('node:buffer').Buffer`
@rename("Buffer")
@native("Buffer")
declare class Buffer {
diff --git a/source/cli/init.hexa b/source/cli/init.hexa
index fbc4f87..1df7848 100644
--- a/source/cli/init.hexa
+++ b/source/cli/init.hexa
@@ -163,5 +163,6 @@ fun init() {
// Detects `y`, `yes` and empty answer as `true`
fun isYes(answer: String): Bool {
+ // TODO code gen must cache this array globally for .includes without allocation
return ['y','yes',''].includes(answer.toLowerCase().trim())
}
diff --git a/source/compiler/lexer.hexa b/source/compiler/lexer.hexa
index f22984c..68660fc 100644
--- a/source/compiler/lexer.hexa
+++ b/source/compiler/lexer.hexa
@@ -58,7 +58,7 @@ class Lexer {
let meta: [Meta] = []
// ^ try the compressed idea for meta's at least TODO
// TODO no zeroing of this buffer when parser is *non*-look-ahead
- let tokens = Buffer.alloc(len + 1) // Note: 1 extra space for Token.Eof
+ let tokens = Buffer.alloc(len + 1) // NOTE 1 extra space for Token.Eof
// TODO ensure optimizer/typer infers `Array` properly
var lines = []
var columns = []
@@ -245,7 +245,7 @@ class Lexer {
// Identifiers and keywords
// A-z _
- // Note: non-ascii identifiers are NOT allowed
+ // NOTE non-ascii identifiers are NOT allowed
// TODO describe the 95 trick
if ((_8 & 95) >= 65 && (_8 & 95) <= 90) or (_8 == 95) {
let title = _8 <= 90
@@ -254,7 +254,7 @@ class Lexer {
// TODO is table lookup really faster than conditions? Bit mask possible>
do {
- // Note: underscore is inside keyword map
+ // NOTE underscore is inside keyword map
// This excludes numbers
allLowercase = allLowercase and (_8 >= 95) // TODO `'_'.charCodeAt(0)`
p++
@@ -326,6 +326,7 @@ class Lexer {
// >>>
// TODO this may be done in parser
+ // ^ if lexer called from parser, it may set flag of not-parsing >>> in templates
if _16 == 15934 and (get_8(position + 2) == ">".charCodeAt(0)) {
add(Token.UnsignedRightShift)
position += 3
diff --git a/source/compiler/normalizer.hexa b/source/compiler/normalizer.hexa
index 42fdb4b..362926f 100644
--- a/source/compiler/normalizer.hexa
+++ b/source/compiler/normalizer.hexa
@@ -876,10 +876,12 @@ class Normalizer {
case As(e, kind, t): switch kind {
case Question:
console.log('`as?` is not yet supported by normalizer, only `as!`')
+ // TODO error/implement
case KNot:
return Expression.UnsafeBitCast(nodeToExpression(e), typer.types.get(t))
case _:
console.log('`as` is not yet supported by normalizer, only `as!`')
+ // TODO error/implement
}
case Is(e, t):
diff --git a/source/compiler/parser.hexa b/source/compiler/parser.hexa
index 4064b62..b6408cb 100644
--- a/source/compiler/parser.hexa
+++ b/source/compiler/parser.hexa
@@ -1902,7 +1902,7 @@ class Parser {
let token = tok()
if
- // Note: don't do it like that! Some type syntax uses lowercases
+ // NOTE don't do it like that! Some type syntax uses lowercases
//tok() != Token.Assign and
//tok() != Token.CallClose and
//tok() != Token.Comma
diff --git a/source/compiler/preprocessor.hexa b/source/compiler/preprocessor.hexa
index 0eac53f..d16d522 100644
--- a/source/compiler/preprocessor.hexa
+++ b/source/compiler/preprocessor.hexa
@@ -42,7 +42,7 @@ class Preprocessor {
private static fun processTokens(tokens: Tokens, i: Int, project: Project): Tokens {
var i = i
var token = tokens.token[0] as! Token
- let bytes = tokens.token.slice() // Note: this creates a copy with all tokens
+ let bytes = tokens.token.slice() // NOTE this creates a copy with all tokens
// TODO Slicing from `i` would cause allocation on ~every array `[to]` insert, any ideas?
// Maybe just allocate Array(len) + copy values upto i, so unused are null
let params = tokens.value.slice()
diff --git a/source/compiler/typer.hexa b/source/compiler/typer.hexa
index dd0bcda..66aae51 100644
--- a/source/compiler/typer.hexa
+++ b/source/compiler/typer.hexa
@@ -2240,14 +2240,15 @@ class Typer {
addScope(name, node)
- // `a op b` like `a + b`
+ // `a = b` as a statement
case Binop(a, op, b):
fillExpression(node)
var parent: Node = parents.get(a)
// `a = b`
// TODO separate assign node? or just nested pattern...
- if op == Token.Assign { switch parent {
+ if op == Token.Assign {
+ switch parent {
case null:
switch a {
case Ident(_): // Ok
@@ -2994,26 +2995,26 @@ class Typer {
// TODO why the heck `.Vname` here gives Ln1, Col 12???
// type.V here is ok, but is in the string interpolator
// ^ should be possible to set starting col/line in Lexer
- // Note: `proposeSimilar` is useless for DotUpper over instances
+ // NOTE `proposeSimilar` is useless for DotUpper over instances
fail('Enum `\(type.name)` instance has no field `.\(n)`', node)
case ClassInstance(type):
failNonFatal('Type `\(type.name)` is defined here', type.parent)
- // Note: `proposeSimilar` is useless for DotUpper over instances
+ // NOTE `proposeSimilar` is useless for DotUpper over instances
fail('Class `\(type.name)` has no field `.\(n)`\n\nNote that you are trying to access plain `class` instance and not `enum`', node)
case Class(type):
failNonFatal('Type `\(type.name)` is defined here', type.parent)
- // Note: `proposeSimilar` is useless for DotUpper over classes
+ // NOTE `proposeSimilar` is useless for DotUpper over classes
fail('Class `\(type.name)` has no field `.\(n)`\n\nNote that you are trying to access `class` and not `enum`', node)
case Enum(type):
let index = type.fieldNames.indexOf(n)
// TODO `@lazy let enumName = getName(type.name)` so no need to place in every failing `if`
if index < 0 {
failNonFatal('Type `\(type.name)` is defined here', type.parent)
- // Note: `proposeSimilar` but only constructors (if any)
+ // NOTE `proposeSimilar` but only constructors (if any)
fail('Enum `\(type.name)` has no value constructor `.\(n)`\n' + proposeSimilar(type.fieldNames.filter((element, index) => type.fieldEnumConstructor[index]), n, 'constructors'), node)
}
if type.fieldEnumConstructor[index] != true {
- // Note: this case is probably impossible, i.e. .N *not* being constructor (than what?)
+ // NOTE this case is probably impossible, i.e. .N *not* being constructor (than what?)
fail('Enum `\(type.name)` field `.\(n)` is not a value constructor', node)
}
if let fieldType = type.fieldType[index] {
@@ -3033,6 +3034,7 @@ class Typer {
if asValue {
fail('Cannot use type `\(name)` as a value, use `\(name)()` to call constructor', node)
}
+
let subj = find(name)
if subj == null {
fail('Cannot find type with name `\(name)`', node)
@@ -3050,7 +3052,8 @@ class Typer {
let mod = currentModule
registerClassType(subj)
currentModule = mod
- case Enum(_): registerEnumType(subj)
+ case Enum(_):
+ registerEnumType(subj)
}
if let type = types.get(subj) {
@@ -3465,6 +3468,7 @@ class Typer {
// TODO `null == null` should error cause no sense
if leftString != 'null', rightString != 'null' {
+ // TODO recommend `.address` for pointers
fail('Operator `a \(tokenString) b` requires `a` and `b` of comparable types, but got `\(leftString)` and `\(rightString)`', b)
}
}
@@ -3773,8 +3777,9 @@ class Typer {
}
if thisType == null {
- fail('Cannot access `this` in class method', node)
+ fail('Cannot access `this` in the static method', node)
}
+
types.set(node, thisType)
parents.set(node, thisNode)
@@ -3784,6 +3789,7 @@ class Typer {
// `return e`
case Return(e):
+ // TODO cannot return from constructor
switch e {
case Var(name, _, _, const):
let prefix = const? 'let' : 'var'
diff --git a/source/data/data.hexa b/source/data/data.hexa
index ca19990..d8dcbf5 100644
--- a/source/data/data.hexa
+++ b/source/data/data.hexa
@@ -101,15 +101,15 @@ enum Node {
/// `declare fun name(vars) retType { body }`
// Name is `new` for constructor
// TODO expr Node.Block (goal is *not* to `Node extends NodeBlock` but to actually limit tags)
- Function(name String?, body Node, vars [Node], retType NodeType, external Bool, variadic Bool)
+ Function(name String?, body Node, vars [Node], returnType NodeType, external Bool, variadic Bool)
- /// (vars) retType => expr
+ /// `(vars) retType => expr`
// TODO parser `: retType` is really needed at all?
Arrow(expr Node, vars [Node], retType NodeType)
- /// [external ? declare] (const ? let : var) name nodeType [= expr]
// `varStatic` =>> `funStatic` `varPrivate` etc
+ /// [external ? `declare`] (const ? `let` : `var`) `name nodeType` [`= expr`]
// TODO `expr Node?`
Var(name String, varType NodeType, expr Node, const Bool, external Bool)
@@ -124,9 +124,11 @@ enum Node {
Try(expr Node, t [NodeType], v [Node], catches [Node])
/// `expr.name`
+ // TODO rename to Field
Dot(expr Node, name String)
/// expr.Name
+ // TODO rename to CapitalField
DotUpper(expr Node, name String)
/// `new T { } (args)` TODO new syntax
@@ -178,20 +180,23 @@ enum Node {
Underscore
/// `...`
+ // TODO support `...expr`
Interval
/// `static` field
+ // TODO drop this
Static(field Node)
/// `private` field or type
+ // TODO drop this
Private(field Node)
/// for name in over by
/// for name in over ... range by
For(name String, over Node, by Node, range Node)
- /// `nullable ?? othewise`
- Elvis(nullable Node, otherwise Node)
+ /// `nullable ?? alternative`
+ Elvis(nullable Node, alternative Node)
/// `T` but as expression
NodeTypeValue(type NodeType)
diff --git a/source/data/nice.hexa b/source/data/nice.hexa
index d484aa2..4b3cee3 100644
--- a/source/data/nice.hexa
+++ b/source/data/nice.hexa
@@ -60,6 +60,7 @@ enum Statement {
Assignop(name Expression, op Token, value Expression)
// TODO ^ `AssignOp`
For(name String, over Expression, by Statement)
+ // TODO why not separate `DoWhile`?
While(econd Expression, e Statement, pre Bool)
Increment(e Expression)
Decrement(e Expression)
diff --git a/source/data/token.hexa b/source/data/token.hexa
index 7110bb9..64a845e 100644
--- a/source/data/token.hexa
+++ b/source/data/token.hexa
@@ -98,7 +98,7 @@ enum Token : Int {
BitwiseNot = 88 // ~
// Binary
- // TODO Note: Op- prefix for names used cause in IR binary operators use Token as operator kind
+ // TODO NOTE Op- prefix for names used cause in IR binary operators use Token as operator kind
// ^ somehow create an enum subset of them?
RightArrow = 90 // =>
Assign = 91 // =
@@ -155,7 +155,7 @@ enum Token : Int {
case KElse: return "else"
case KEnum: return "enum"
case KExtends: return "extends"
- // Note: `declare` instantly creates TypeScript vibe and must be kept
+ // NOTE `declare` instantly creates TypeScript vibe and must be kept
case KDeclare: return "declare"
case KFalse: return "false"
case KFor: return "for"
diff --git a/source/main.hexa b/source/main.hexa
index 17da6af..4d9166a 100644
--- a/source/main.hexa
+++ b/source/main.hexa
@@ -151,7 +151,7 @@ class Main {
if named {
let name = DataHelper.nameOf(e)
- if (project.globals.has(name)) {
+ if project.globals.has(name) {
let data = project.data.get(e)
let already = project.data.get(project.globals.get(name))
let msg = "Global node `\(name)` declared in `\(path)` already defined at `\(already.fileName)` line `\(already.line)`"
@@ -619,7 +619,7 @@ class Main {
console.log("[Building \(input.name)]")
}
- console.log("[Using 1 of \(require('os').cpus().length) CPU cores]")
+ console.log("[Using 1 of \(require('os').cpus().length) CPU threads]")
// TODO ^ fix syntax highlighting for \parenthesis pairs
}
}
diff --git a/source/targets/genC.hexa b/source/targets/genC.hexa
index 98f299f..38bc72b 100644
--- a/source/targets/genC.hexa
+++ b/source/targets/genC.hexa
@@ -32,6 +32,7 @@ class GenCxx {
fun perform(normalizer, target: String, options: [String]): String {
project = normalizer
extraUnderscore = options.includes('extraUnderscore')
+ // TODO report unsupported options
return stringify(target)
}
@@ -113,10 +114,12 @@ class GenCxx {
// No need to output simple enum values
// TODO proper base type
forward.push('struct ' + e.name + '_;')
- if (e.staticVars.length + e.staticMethods.length == 0) {
+ if e.staticVars.length + e.staticMethods.length == 0 {
continue
}
+
// TODO tdef C* C
+ // TODO this seem to be a leftover from C++
types.push('struct ' + e.name + '_ {\n\t')
// Static vars before static functions
@@ -322,6 +325,7 @@ class GenCxx {
if isPacked {
types.push('#pragma pack(1)\n')
}
+
types.push(nativeKind + c.name + '_ {\n\t')
let vtable = ['struct ' + c.name + '__ {\n\t']
// TODO const pointer to const struct
@@ -608,7 +612,7 @@ class GenCxx {
customHeader = link.customHeader
}
- // Note: before `dllExports.push`
+ // NOTE before `dllExports.push`
if let rename = link.rename {
name = rename
}
@@ -751,6 +755,7 @@ class GenCxx {
if value != '(int32_t)0' {
out.push('\t' + name + '_ = ' + value + ';\n')
}
+ // TODO init them at declaration! int a = 123;
}
}
//out.push('\n\tvar ' + name)
@@ -772,11 +777,11 @@ class GenCxx {
}
let init = printStatement(project.init[0])
- // Note: strings should be gathered after ALL expressions printed
+ // NOTE strings should be gathered after ALL expressions printed
// TODO may be [] length == 0
let strings: [String] = ['\tString_$root_ = String_$new_();\n']
for id in declarationsOfStrings.length {
- // Note: `const char[]` causes compiler to make a copy of the entire string on every usage
+ // NOTE `const char[]` causes compiler to make a copy of the entire string on every usage
// TODO set ref counting
//strings.push('\tString_Strings[\(id)] = String_fromUTF8z("\(declarationsOfStrings[id])");\n')
strings.push('\tString_\(id) = String_$fromUTF16z_((const uint16_t*)String_\(id)_);\n')
@@ -1112,6 +1117,7 @@ class GenCxx {
if generics[0] == project.typer.typeUInt8 {
return stringifyType(valueType) + ' ' + name + '_' + arraySize + ' = "' + string + '"'
}
+
if generics[0] == project.typer.typeUInt16 {
return stringifyType(valueType) + ' ' + name + '_' + arraySize + ' = L"' + string + '"'
}
@@ -1535,7 +1541,7 @@ class GenCxx {
return '%printNullableToValueConverter%'
}
- /// Note: this is a strict `as!` kind of conversion
+ /// NOTE this is a strict `as!` kind of conversion
fun printTypeConverter(string: String, fromValue: Type, to: Type): String {
if fromValue == to {
return string
@@ -1738,7 +1744,7 @@ class GenCxx {
(fromValue == project.typer.typeNullFloat32 and to == project.typer.typeFloat32)
{
return string + '.value_'
- // Note: no need to validate `has_` cause `null => has_ == 0 and value == 0`
+ // NOTE no need to validate `has_` cause `null => has_ == 0 and value == 0`
}
return string + '/*T = T?*/'
return '%T = T?%'
diff --git a/source/targets/genNasm.hexa b/source/targets/genNasm.hexa
index 7c29748..85a34ef 100644
--- a/source/targets/genNasm.hexa
+++ b/source/targets/genNasm.hexa
@@ -154,7 +154,7 @@ class NasmFunction {
} else if stackStorage != 0 {
body.unshift('sub RSP, \(stackStorage)')
}
- body.unshift('push RBP; Set stack frame') // Note: `unshift` works in reverse order
+ body.unshift('push RBP; Set stack frame') // NOTE `unshift` works in reverse order
// TODO add ret only if not done
}
@@ -881,7 +881,7 @@ class GenNasm {
let typeStrings: [Type : String] = [:]
- // Note: returns with ending space
+ // NOTE returns with ending space
fun typeToString(type: Type): String {
if let string = typeStrings.get(type) {
return string
@@ -1089,7 +1089,7 @@ class GenNasm {
if asC {
// TODO mirror \n \t etc
dataSection.push('static const wchar_t *String\(id) = L"\(text)";')
- // Note: `const char[]` causes compiler to make a copy of the entire string on every usage
+ // NOTE `const char[]` causes compiler to make a copy of the entire string on every usage
bssSection.push("static struct String_* String$\(id);")
} else {
dataSection.push("String.\(id) dw __utf16le__('\(text)'), 0")
diff --git a/source/tests/testTyper.hexa b/source/tests/testTyper.hexa
index 363bee0..e2721e0 100644
--- a/source/tests/testTyper.hexa
+++ b/source/tests/testTyper.hexa
@@ -398,6 +398,10 @@ class TestTyper {
shouldNotError('var x = 0 var z = x += 0 z = 0')
shouldError('var x = 0 var z = x += 0 z = true')
+ // `shouldError('[var/let] a = []')` // `[]` may be Map or Array or keep `[:]`
+ // ^ must error at `[]` node itself when fail to infer its type
+ // same for generic args `fun (generic)` TODO
+
// Typing is
shouldNotError('let t = 1 t is Int')
shouldError('let t = 1 t is Any')
@@ -445,6 +449,7 @@ class TestTyper {
shouldError("declare fun f()")
shouldNotError("declare fun f(): Int")
shouldError("var a = declare fun f(): Int")
+ // TODO `declare A = A` some recursion, A=B, B=A etc, also Int=A
// Decorators
shouldNotError('@att("value") 123')