Skip to content

Commit

Permalink
jule: use arbitrary-big numbers for untyped constants
Browse files Browse the repository at this point in the history
  • Loading branch information
mertcandav committed Feb 26, 2025
1 parent 09084a8 commit 2c03716
Show file tree
Hide file tree
Showing 16 changed files with 827 additions and 477 deletions.
16 changes: 6 additions & 10 deletions src/julec/obj/cxx/expr.jule
Original file line number Diff line number Diff line change
Expand Up @@ -150,21 +150,17 @@ impl exprCoder {
|:
self.float64(c)
}
| c.IsI64():
| c.IsInt():
i := c.ReadInt()
if c.Kind != "" {
self.oc.tc.toType(self.oc.Buf, c.Kind)
self.oc.write("(")
}
itoa(self.oc.Buf, c.ReadI64())
if c.Kind != "" {
self.oc.write(")")
}
| c.IsU64():
if c.Kind != "" {
self.oc.tc.toType(self.oc.Buf, c.Kind)
self.oc.write("(")
if i.IsI64() {
itoa(self.oc.Buf, i.I64())
} else {
utoa(self.oc.Buf, i.U64())
}
utoa(self.oc.Buf, c.ReadU64())
if c.Kind != "" {
self.oc.write(")")
}
Expand Down
26 changes: 12 additions & 14 deletions src/julec/obj/equal.jule
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,10 @@ fn TypeData(&m: sema::Expr): uintptr {
ret uintptr(unsafe { (*anyData)(&m).typePtr })
}

fn equalConst(l: &constant::Const, r: &constant::Const): bool {
fn equalConst(mut l: &constant::Const, mut r: &constant::Const): bool {
match {
| l.IsI64():
ret r.IsI64() && l.ReadI64() == r.ReadI64()
| l.IsU64():
ret r.IsU64() && l.ReadU64() == r.ReadU64()
| l.IsInt():
ret r.IsInt() && l.ReadInt().Cmp(r.ReadInt()) == 0
| l.IsF64():
ret r.IsF64() && l.ReadF64() == r.ReadF64()
| l.IsStr():
Expand All @@ -34,26 +32,26 @@ fn equalConst(l: &constant::Const, r: &constant::Const): bool {
}
}

fn equalCasting(l: &sema::CastingExpr, r: &sema::CastingExpr): bool {
fn equalCasting(mut l: &sema::CastingExpr, mut r: &sema::CastingExpr): bool {
if !l.Type.Equal(r.Type) {
ret false
}
ret EqualModels(l.Expr.Model, r.Expr.Model)
}

fn equalUnary(l: &sema::UnaryExpr, r: &sema::UnaryExpr): bool {
fn equalUnary(mut l: &sema::UnaryExpr, mut r: &sema::UnaryExpr): bool {
if l.Op.Id != r.Op.Id || l.Op.Kind != r.Op.Kind {
ret false
}
ret EqualModels(l.Expr.Model, r.Expr.Model)
}

fn equalIndexing(l: &sema::IndexingExpr, r: &sema::IndexingExpr): bool {
fn equalIndexing(mut l: &sema::IndexingExpr, mut r: &sema::IndexingExpr): bool {
ret EqualModels(l.Expr.Model, r.Expr.Model) &&
EqualModels(l.Index.Model, r.Index.Model)
}

fn equalBinary(l: &sema::BinaryExpr, r: &sema::BinaryExpr): bool {
fn equalBinary(mut l: &sema::BinaryExpr, mut r: &sema::BinaryExpr): bool {
if l.Op.Id != r.Op.Id || l.Op.Kind != r.Op.Kind {
ret false
}
Expand All @@ -64,14 +62,14 @@ fn equalBinary(l: &sema::BinaryExpr, r: &sema::BinaryExpr): bool {
// Reports whether expressions are equal.
// Designed lvalue equality comparison oriented,
// such as swap statement value comparisons.
fn EqualModels(l: sema::Expr, r: sema::Expr): bool {
fn EqualModels(mut l: sema::Expr, mut r: sema::Expr): bool {
if TypeData(l) != TypeData(r) {
ret false
}
match type l {
| &sema::Var:
lv := (&sema::Var)(l)
rv := (&sema::Var)(r)
mut lv := (&sema::Var)(l)
mut rv := (&sema::Var)(r)
if !lv.Reference && !rv.Reference ||
lv.ValueSym == nil || lv.ValueSym.Value == nil ||
rv.ValueSym == nil || rv.ValueSym.Value == nil {
Expand All @@ -91,8 +89,8 @@ fn EqualModels(l: sema::Expr, r: sema::Expr): bool {
}
ret EqualModels(l, rv.ValueSym.Value.Model)
| &sema::StructSubIdentExpr:
li := (&sema::StructSubIdentExpr)(l)
ri := (&sema::StructSubIdentExpr)(r)
mut li := (&sema::StructSubIdentExpr)(l)
mut ri := (&sema::StructSubIdentExpr)(r)
ret li.Field == ri.Field && EqualModels(li.Expr.Model, ri.Expr.Model)
| &constant::Const:
ret equalConst((&constant::Const)(l), (&constant::Const)(r))
Expand Down
26 changes: 13 additions & 13 deletions src/julec/opt/boundary.jule
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ impl boundary {
for i < len(self.vars); i++ {
mut &v := unsafe { *(&self.vars[i]) }
if v.var == var {
for j, max in v.maxSize {
for (j, mut max) in v.maxSize {
if fitsSize(maxSize, max) {
// Maximum size is fits, so new size is larger than current size.
v.maxSize[j] = maxSize
Expand Down Expand Up @@ -75,9 +75,9 @@ impl boundary {
}

// Reports whether maximum size of variable is fits with given expression.
fn fitsMaxSize(mut self, var: uintptr, expr: sema::Expr): bool {
fn fitsMaxSize(mut self, var: uintptr, mut expr: sema::Expr): bool {
if var != invalidBoundary {
for _, v in self.vars {
for (_, mut v) in self.vars {
if v.var == var {
ret fitsMaxSize(v.maxSize, expr) != -1
}
Expand All @@ -88,21 +88,21 @@ impl boundary {
}

// Reports whether model is valid maximum size information for boundary analysis.
fn isValidBoundaryInfo(m: sema::Expr): bool { ret fitsSize(m, m) }
fn isValidBoundaryInfo(mut m: sema::Expr): bool { ret fitsSize(m, m) }

// Reports whether maximum size is fits with given expression.
// In other words, reports whether: max >= expr
// Returns index number of max size which is fit, otherwise -1.
fn fitsMaxSize(max: []sema::Expr, expr: sema::Expr): int {
for i, m in max {
fn fitsMaxSize(mut max: []sema::Expr, mut expr: sema::Expr): int {
for (i, mut m) in max {
if fitsSize(m, expr) {
ret i
}
}
ret -1
}

fn fitsSize(e1: sema::Expr, e2: sema::Expr): bool {
fn fitsSize(mut e1: sema::Expr, mut e2: sema::Expr): bool {
if obj::TypeData(e1) != obj::TypeData(e2) {
ret false
}
Expand All @@ -113,12 +113,12 @@ fn fitsSize(e1: sema::Expr, e2: sema::Expr): bool {
| &sema::Var:
ret e1 == e2
| &sema::StructSubIdentExpr:
ssi1 := (&sema::StructSubIdentExpr)(e1)
ssi2 := (&sema::StructSubIdentExpr)(e2)
mut ssi1 := (&sema::StructSubIdentExpr)(e1)
mut ssi2 := (&sema::StructSubIdentExpr)(e2)
ret obj::EqualModels(ssi1.Expr.Model, ssi2.Expr.Model) && ssi1.Field == ssi2.Field
| &sema::UnaryExpr:
uem1 := (&sema::UnaryExpr)(e1)
uem2 := (&sema::UnaryExpr)(e2)
mut uem1 := (&sema::UnaryExpr)(e1)
mut uem2 := (&sema::UnaryExpr)(e2)
if uem1.Op.Id != token::Id.Star || uem1.Op.Id != uem2.Op.Id {
ret false
}
Expand All @@ -131,7 +131,7 @@ fn fitsSize(e1: sema::Expr, e2: sema::Expr): bool {
// Removes model from boundary b. If model exist in boundary b as a boundary
// exihibit variable, removed variable directly. Otherwise removes size variable
// by model if exist.
fn possibleBoundaryRemove(mut &b: &boundary, model: sema::Expr) {
fn possibleBoundaryRemove(mut &b: &boundary, mut model: sema::Expr) {
// Remove variable from boundary b if exist.
// Because it changed and we don not know anything now.
match type model {
Expand All @@ -145,7 +145,7 @@ fn possibleBoundaryRemove(mut &b: &boundary, model: sema::Expr) {
mut i := 0
for i < len(b.vars); i++ {
mut &v := unsafe { *(&b.vars[i]) }
for j, max in v.maxSize {
for (j, mut max) in v.maxSize {
if obj::EqualModels(max, model) {
v.maxSize = append(v.maxSize[:j], v.maxSize[j+1:]...)
break
Expand Down
6 changes: 3 additions & 3 deletions src/julec/opt/scope.jule
Original file line number Diff line number Diff line change
Expand Up @@ -740,15 +740,15 @@ impl scopeOptimizer {

// resports whether m used in different operand in left or right
// if checkTup equals to false, tuple expression will not be checked
existInOperands := fn(i: int, m: sema::Expr, checkTup: bool): bool {
existInOperands := fn(i: int, mut m: sema::Expr, checkTup: bool): bool {
// check whether variable used in different operand in left or right
for j, jl in unsafe { assign.Left } {
for (j, mut jl) in unsafe { assign.Left } {
for j != i && jl != nil && obj::EqualModels(jl.Model, m) {
ret true
}
}
if checkTup {
for j, jl in unsafe { tup.Values } {
for (j, mut jl) in unsafe { tup.Values } {
for j != i && jl != nil && obj::EqualModels(jl.Model, m) {
ret true
}
Expand Down
6 changes: 5 additions & 1 deletion std/jule/build/log.jule
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ enum LogMsg: str {
FuncHaveParameters: `function @ doesn't require any parameters`,
RequireRetExpr: `non-void functions should return a value`,
VoidFuncRetExpr: `void functions cannot return a value`,
BitShiftMustUnsigned: `bit shifting value must be unsigned`,
BitShiftMustUnsigned: `bit shifting value must be unsigned integer`,
InvalidShiftCount: `invalid shift count: @`,
LogicalNotBool: `logical expression must be boolean`,
AssignConst: `constants cannot be assigned`,
AssignRequireLvalue: `invalid expression: expected lvalue`,
Expand Down Expand Up @@ -263,6 +264,9 @@ enum LogMsg: str {
FinalIndexRequired: `final index required in 3-index slicing`,
UnsupportedTypeIndex3Slice: `unsupported type for 3-index slicing: @`,
ReuseDirective: `directive @ is already used`,
ConstantOverflow: `constant overflow`,
ConstantOverflowResult: `computation result is constant overflow`,
UntypedNumericForPhysical: `cannot use untyped value @ for the actual program, it is too large for any integer type`,

// Suggestions.
ExpectedIdentifier: `create an identifier because identifier expected`,
Expand Down
Loading

0 comments on commit 2c03716

Please sign in to comment.