Skip to content

Commit 57b1328

Browse files
committed
v2: major transformer, cleanc codegen, and checker improvements
- Expand transformer with smart cast handling, compound conditions, nested maps, array type normalization, and filter expressions - Enhance cleanc code generator with better type handling and remove stubs in favor of proper type info from Environment - Add comprehensive checker_test.v with 477 lines of type checking tests - Expand test.v with many more test cases (+794 lines) - Add interface support and if-guards handling - Fix various edge cases in expression mapping and string generation
1 parent c16d11b commit 57b1328

13 files changed

Lines changed: 8047 additions & 1409 deletions

File tree

‎cmd/v2/test.v‎

Lines changed: 945 additions & 2 deletions
Large diffs are not rendered by default.

‎cmd/v2/test_v2_self.sh‎

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,26 @@ rm v2 || true
66
v v2.v
77

88
rm v3 || true
9+
rm v3.c || true
910
# Use v2 to compile itself to v3 (using cleanc backend)
1011
./v2 -o v3 -backend cleanc v2.v || exit
1112

12-
# Use v3 to compile hello world
13-
#./v3 -backend cleanc hello.v
14-
./v3 || true
13+
echo "SUCCESS: v2 successfully compiled itself to v3"
14+
echo "v3 binary size: $(ls -lh v3 | awk '{print $5}')"
1515

16-
# Test that v3 without args prints the expected error message
16+
# Test that v3 runs and produces expected output
1717
OUTPUT=$(./v3 2>&1 || true)
1818
EXPECTED="At least 1 .v file expected"
1919

2020
if echo "$OUTPUT" | grep -q "$EXPECTED"; then
21-
echo "SUCCESS: v3 works correctly and prints expected message"
21+
echo "SUCCESS: v3 runs correctly and prints expected message"
2222
else
2323
echo "FAILURE: Expected '$EXPECTED' but got:"
2424
echo "$OUTPUT"
2525
exit 1
2626
fi
27+
28+
echo ""
29+
echo "=== SELF-COMPILATION TEST PASSED ==="
30+
echo "Note: v3 uses stubbed functions for complex modules."
31+
echo "Full bootstrap requires fixing remaining issues in cleanc module."

‎vlib/v/parser/tmpl.v‎

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -529,43 +529,49 @@ fn veb_tmpl_${fn_name}() string {
529529
else {}
530530
}
531531

532-
if pos := line.index('%') {
533-
// %translation_key => ${tr('translation_key')}
534-
is_raw := line.contains('%raw ')
535-
mut line_ := line
532+
// %translation_key => ${tr('translation_key')}
533+
// Process all %key patterns on this line
534+
mut line_ := line
535+
mut search_start := 0
536+
for {
537+
pos := line_.index_after('%', search_start) or { break }
538+
is_raw := pos + 4 < line_.len && line_[pos..pos + 5] == '%raw '
536539
if is_raw {
537-
// Start reading the key after "raw " (pos + 1 + 4)
540+
// Start reading the key after "raw " (pos + 5)
538541
mut end := pos + 5
539542
// valid variable characters
540-
for end < line.len && (line[end].is_letter() || line[end] == `_`) {
543+
for end < line_.len && (line_[end].is_letter() || line_[end] == `_`) {
541544
end++
542545
}
543546
// Extract the key
544-
key := line[pos + 5..end]
545-
// Replace '%raw key' with just '${key}'
546-
// We escape it as \${key} so the generated V code performs the interpolation
547-
// line_ = line.replace('%raw ${key}', '\${${key}}')
548-
line_ = line.replace('%raw ${key}', '\${veb.raw(veb.tr(ctx.lang.str(), "${key}"))}')
547+
key := line_[pos + 5..end]
548+
if key.len > 0 {
549+
// Replace '%raw key' with just '${key}'
550+
line_ = line_.replace('%raw ${key}', '\${veb.raw(veb.tr(ctx.lang.str(), "${key}"))}')
551+
}
552+
search_start = pos + 1
549553
} else {
550-
if pos + 1 < line.len && line[pos + 1].is_letter() { //|| line[pos + 1] == '_' {
554+
if pos + 1 < line_.len && line_[pos + 1].is_letter() {
551555
mut end := pos + 1
552-
for end < line.len && (line[end].is_letter() || line[end] == `_`) {
556+
for end < line_.len && (line_[end].is_letter() || line_[end] == `_`) {
553557
end++
554558
}
555-
key := line[pos + 1..end]
556-
// println('GOT tr key line="${line}" key="${key}"')
557-
// source.writeln('\${tr("${key}")}')
558-
line_ = line.replace('%${key}', '\${veb.tr(ctx.lang.str(), "${key}")}')
559-
// i += key.len
559+
key := line_[pos + 1..end]
560+
// println('GOT tr key line="${line_}" key="${key}"')
561+
line_ = line_.replace('%${key}', '\${veb.tr(ctx.lang.str(), "${key}")}')
562+
search_start = pos + 1
563+
} else {
564+
// Not a valid translation key, skip this %
565+
search_start = pos + 1
560566
}
561567
}
562-
// println(source.str())
568+
}
569+
if line_ != line {
563570
source.writeln(insert_template_code(fn_name, tmpl_str_start, line_))
564571
p.template_line_map << ast.TemplateLineInfo{
565572
tmpl_path: template_file
566573
tmpl_line: tline_number
567574
}
568-
// exit(0)
569575
} else {
570576
// by default, just copy 1:1
571577
source.writeln(insert_template_code(fn_name, tmpl_str_start, line))

‎vlib/v2/ast/ast.v‎

Lines changed: 85 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,12 @@ pub fn (expr Expr) pos() token.Pos {
193193
ArrayInitExpr {
194194
expr.pos
195195
}
196+
AssocExpr {
197+
expr.pos
198+
}
199+
BasicLiteral {
200+
expr.pos
201+
}
196202
CallExpr {
197203
expr.pos
198204
}
@@ -205,35 +211,89 @@ pub fn (expr Expr) pos() token.Pos {
205211
ComptimeExpr {
206212
expr.pos
207213
}
214+
FnLiteral {
215+
expr.pos
216+
}
217+
GenericArgOrIndexExpr {
218+
expr.pos
219+
}
220+
GenericArgs {
221+
expr.pos
222+
}
208223
Ident {
209224
expr.pos
210225
}
226+
IfExpr {
227+
expr.pos
228+
}
229+
IfGuardExpr {
230+
expr.pos
231+
}
232+
IndexExpr {
233+
expr.pos
234+
}
211235
InfixExpr {
212236
expr.pos
213237
}
238+
InitExpr {
239+
expr.pos
240+
}
241+
KeywordOperator {
242+
expr.pos
243+
}
244+
LambdaExpr {
245+
expr.pos
246+
}
247+
LockExpr {
248+
expr.pos
249+
}
214250
MapInitExpr {
215251
expr.pos
216252
}
217253
MatchExpr {
218254
expr.pos
219255
}
256+
ModifierExpr {
257+
expr.pos
258+
}
220259
OrExpr {
221260
expr.pos
222261
}
262+
ParenExpr {
263+
expr.pos
264+
}
265+
PostfixExpr {
266+
expr.pos
267+
}
223268
PrefixExpr {
224269
expr.pos
225270
}
271+
RangeExpr {
272+
expr.pos
273+
}
226274
SelectExpr {
227275
expr.pos
228276
}
229277
SelectorExpr {
230278
expr.pos
231-
// NOTE: should we remove `pos` from `SelectorExpr` and use `expr.lhs.pos()` instead?
232-
// which would always get the position of the left most part of the `SelectorExpr`
233-
// expr.lhs.pos()
279+
}
280+
SqlExpr {
281+
expr.pos
282+
}
283+
StringInterLiteral {
284+
expr.pos
285+
}
286+
StringLiteral {
287+
expr.pos
288+
}
289+
Tuple {
290+
expr.pos
291+
}
292+
UnsafeExpr {
293+
expr.pos
234294
}
235295
else {
236-
// Default for expressions without pos field
296+
// Default for expressions without pos field (EmptyExpr, FieldInit, Keyword, Type)
237297
0
238298
}
239299
}
@@ -291,12 +351,14 @@ pub:
291351
typ Expr
292352
expr Expr
293353
fields []FieldInit
354+
pos token.Pos
294355
}
295356

296357
pub struct BasicLiteral {
297358
pub:
298359
kind token.Token
299360
value string
361+
pos token.Pos
300362
}
301363

302364
pub struct CallExpr {
@@ -346,18 +408,21 @@ pub:
346408
typ FnType
347409
captured_vars []Expr
348410
stmts []Stmt
411+
pos token.Pos
349412
}
350413

351414
pub struct GenericArgs {
352415
pub:
353416
lhs Expr
354417
args []Expr // concrete types
418+
pos token.Pos
355419
}
356420

357421
pub struct GenericArgOrIndexExpr {
358422
pub:
359423
lhs Expr
360424
expr Expr
425+
pos token.Pos
361426
}
362427

363428
pub struct Ident {
@@ -371,11 +436,13 @@ pub:
371436
cond Expr = empty_expr
372437
else_expr Expr = empty_expr
373438
stmts []Stmt
439+
pos token.Pos
374440
}
375441

376442
pub struct IfGuardExpr {
377443
pub:
378444
stmt AssignStmt
445+
pos token.Pos
379446
}
380447

381448
pub struct InfixExpr {
@@ -391,12 +458,14 @@ pub:
391458
lhs Expr
392459
expr Expr
393460
is_gated bool
461+
pos token.Pos
394462
}
395463

396464
pub struct InitExpr {
397465
pub:
398466
typ Expr
399467
fields []FieldInit
468+
pos token.Pos
400469
}
401470

402471
pub struct Keyword {
@@ -408,24 +477,28 @@ pub struct KeywordOperator {
408477
pub:
409478
op token.Token
410479
exprs []Expr
480+
pos token.Pos
411481
}
412482

413483
pub struct Tuple {
414484
pub:
415485
exprs []Expr
486+
pos token.Pos
416487
}
417488

418489
pub struct LambdaExpr {
419490
pub:
420491
args []Ident
421492
expr Expr
493+
pos token.Pos
422494
}
423495

424496
pub struct LockExpr {
425497
pub:
426498
lock_exprs []Expr
427499
rlock_exprs []Expr
428500
stmts []Stmt
501+
pos token.Pos
429502
}
430503

431504
pub struct MapInitExpr {
@@ -468,6 +541,7 @@ pub struct ModifierExpr {
468541
pub:
469542
kind token.Token
470543
expr Expr
544+
pos token.Pos
471545
}
472546

473547
// pub fn (expr ModifierExpr) unwrap() Expr {
@@ -492,12 +566,14 @@ pub:
492566
pub struct ParenExpr {
493567
pub:
494568
expr Expr
569+
pos token.Pos
495570
}
496571

497572
pub struct PostfixExpr {
498573
pub:
499574
op token.Token
500575
expr Expr
576+
pos token.Pos
501577
}
502578

503579
pub struct PrefixExpr {
@@ -512,6 +588,7 @@ pub:
512588
op token.Token // `..` exclusive | `...` inclusive
513589
start Expr
514590
end Expr
591+
pos token.Pos
515592
}
516593

517594
pub struct SelectExpr {
@@ -587,13 +664,15 @@ pub struct StringLiteral {
587664
pub:
588665
kind StringLiteralKind
589666
value string
667+
pos token.Pos
590668
}
591669

592670
pub struct StringInterLiteral {
593671
pub:
594672
kind StringLiteralKind
595673
values []string
596674
inters []StringInter
675+
pos token.Pos
597676
}
598677

599678
pub struct StringInter {
@@ -656,11 +735,13 @@ pub fn (sif StringInterFormat) str() string {
656735
pub struct SqlExpr {
657736
pub:
658737
expr Expr
738+
pos token.Pos
659739
}
660740

661741
pub struct UnsafeExpr {
662742
pub:
663743
stmts []Stmt
744+
pos token.Pos
664745
}
665746

666747
// Statements

0 commit comments

Comments
 (0)