Skip to content

Commit 24eb6ef

Browse files
committed
v2: comptime if; fmt
1 parent dfc111d commit 24eb6ef

4 files changed

Lines changed: 356 additions & 15 deletions

File tree

‎cmd/v2/test.v‎

Lines changed: 58 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ enum Color {
2727

2828
enum Status {
2929
pending = 0
30-
active = 1
31-
done = 2
30+
active = 1
31+
done = 2
3232
}
3333

3434
// Interface declaration
@@ -248,6 +248,19 @@ fn nested_return(x int) int {
248248
}
249249
}
250250

251+
// Helper for comptime test
252+
fn get_comptime_value() int {
253+
$if macos {
254+
return 50
255+
} $else $if linux {
256+
return 51
257+
} $else $if windows {
258+
return 52
259+
} $else {
260+
return 59
261+
}
262+
}
263+
251264
// Function using type alias (type alias is same as base type in C)
252265
fn add_my_ints(a int, b int) int {
253266
return a + b
@@ -258,21 +271,21 @@ fn defer_test() int {
258271
mut x := 0
259272
defer {
260273
x = 42
261-
};
274+
}
262275
return x + 42 // Return 42, but x is modified by defer before return
263276
}
264277

265278
// Helper function to test defer order (LIFO)
266279
fn defer_order_test() {
267280
defer {
268281
print_str('First')
269-
};
282+
}
270283
defer {
271284
print_str('Second')
272-
};
285+
}
273286
defer {
274287
print_str('Third')
275-
};
288+
}
276289
}
277290

278291
// ===================== IF-GUARD HELPERS =====================
@@ -1940,28 +1953,27 @@ fn main() {
19401953
g_val = 0
19411954
defer {
19421955
g_val += 100
1943-
};
1956+
}
19441957
g_val += 1
19451958
print_int(g_val) // 1 (defer not executed yet, will be 101 at function end)
19461959

19471960
// 38.2 Multiple defers execute in reverse order (LIFO)
19481961
g_count = 0
19491962
defer {
19501963
g_count += 1
1951-
};
1964+
}
19521965
defer {
19531966
g_count += 10
1954-
};
1967+
}
19551968
defer {
19561969
g_count += 100
1957-
};
1970+
}
19581971
// At end of function: g_count = 0 + 100 + 10 + 1 = 111
19591972

19601973
// 38.3 Defer with function call
19611974
defer {
19621975
print_str('Defer 38.3 executed')
1963-
};
1964-
1976+
}
19651977
// 38.4 Test defer_test function with explicit return
19661978
print_int(defer_test()) // Should print 42
19671979

@@ -2164,5 +2176,39 @@ fn main() {
21642176
}
21652177
print_int(my_sum) // 1+2+3+4+5 = 15
21662178

2179+
// ==================== 44. COMPTIME ====================
2180+
print_str('--- 44. Comptime ---')
2181+
2182+
// 44.1 Basic $if macos/$else
2183+
$if macos {
2184+
print_int(1) // 1 on macOS
2185+
} $else {
2186+
print_int(0) // 0 on other platforms
2187+
}
2188+
2189+
// 44.2 $if linux
2190+
$if linux {
2191+
print_int(2) // 2 on Linux
2192+
} $else {
2193+
print_int(20) // 20 on non-Linux
2194+
}
2195+
2196+
// 44.3 $if windows
2197+
$if windows {
2198+
print_int(3) // 3 on Windows
2199+
} $else {
2200+
print_int(30) // 30 on non-Windows
2201+
}
2202+
2203+
// 44.4 Negation: $if !windows
2204+
$if !windows {
2205+
print_int(4) // 4 on non-Windows
2206+
} $else {
2207+
print_int(40) // 40 on Windows
2208+
}
2209+
2210+
// 44.5 Comptime in function call
2211+
print_int(get_comptime_value())
2212+
21672213
print_str('=== All tests completed ===')
21682214
}

‎cmd/v2/test_ssa_backends.v‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,8 @@ fn main() {
192192
}
193193
// Strip terminal control characters that script command may prepend
194194
// This includes: ^D (literal), ctrl-D (0x04), backspace (0x08), carriage return, etc.
195-
mut cleaned := gen_res.output.replace('\r\n', '\n').replace('\x04', '').replace('\x08', '')
195+
mut cleaned := gen_res.output.replace('\r\n', '\n').replace('\x04', '').replace('\x08',
196+
'')
196197
// Remove "^D" literal string that macOS script may add
197198
if cleaned.starts_with('^D') {
198199
cleaned = cleaned[2..]

‎vlib/v2/gen/cleanc/cleanc.v‎

Lines changed: 146 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1089,7 +1089,8 @@ fn (mut g Gen) gen_expr(node ast.Expr) {
10891089
name = node.lhs.name
10901090
// Check if this is a primitive type cast (int, i64, etc.)
10911091
// For enums, int(enum_val) just returns the value since C enums are ints
1092-
if name in ['int', 'i64', 'i32', 'i16', 'i8', 'u64', 'u32', 'u16', 'u8', 'f32', 'f64'] {
1092+
if name in ['int', 'i64', 'i32', 'i16', 'i8', 'u64', 'u32', 'u16', 'u8', 'f32',
1093+
'f64'] {
10931094
g.sb.write_string('((${name})(')
10941095
g.gen_expr(node.expr)
10951096
g.sb.write_string('))')
@@ -1250,12 +1251,156 @@ fn (mut g Gen) gen_expr(node ast.Expr) {
12501251
g.gen_expr(node.end)
12511252
g.sb.write_string('}')
12521253
}
1254+
ast.ComptimeExpr {
1255+
// Handle comptime expressions like $if macos { ... } $else { ... }
1256+
g.gen_comptime_expr(node)
1257+
}
12531258
else {
12541259
g.sb.write_string('/* expr: ${node.type_name()} */')
12551260
}
12561261
}
12571262
}
12581263

1264+
// gen_comptime_expr handles compile-time conditionals like $if macos { ... } $else { ... }
1265+
fn (mut g Gen) gen_comptime_expr(node ast.ComptimeExpr) {
1266+
// The inner expression should be an IfExpr
1267+
if node.expr is ast.IfExpr {
1268+
g.gen_comptime_if(node.expr)
1269+
} else {
1270+
// For other comptime expressions, just emit them
1271+
g.gen_expr(node.expr)
1272+
}
1273+
}
1274+
1275+
// gen_comptime_if handles $if/$else compile-time conditionals
1276+
fn (mut g Gen) gen_comptime_if(node ast.IfExpr) {
1277+
// Evaluate the comptime condition
1278+
cond_result := g.eval_comptime_cond(node.cond)
1279+
1280+
if cond_result {
1281+
// Condition is true - emit then branch
1282+
g.gen_stmts(node.stmts)
1283+
} else {
1284+
// Condition is false - emit else branch if present
1285+
if node.else_expr !is ast.EmptyExpr {
1286+
if node.else_expr is ast.IfExpr {
1287+
// Could be $else if or plain $else
1288+
if node.else_expr.cond is ast.EmptyExpr {
1289+
// Plain $else block
1290+
g.gen_stmts(node.else_expr.stmts)
1291+
} else {
1292+
// $else $if - recursive comptime evaluation
1293+
g.gen_comptime_if(node.else_expr)
1294+
}
1295+
}
1296+
}
1297+
}
1298+
}
1299+
1300+
// eval_comptime_cond evaluates a compile-time condition expression
1301+
fn (g Gen) eval_comptime_cond(cond ast.Expr) bool {
1302+
match cond {
1303+
ast.Ident {
1304+
// Platform and feature flags
1305+
return g.eval_comptime_flag(cond.name)
1306+
}
1307+
ast.PrefixExpr {
1308+
// Handle negation: !macos
1309+
if cond.op == .not {
1310+
return !g.eval_comptime_cond(cond.expr)
1311+
}
1312+
}
1313+
ast.InfixExpr {
1314+
// Handle && and ||
1315+
if cond.op == .and {
1316+
return g.eval_comptime_cond(cond.lhs) && g.eval_comptime_cond(cond.rhs)
1317+
}
1318+
if cond.op == .logical_or {
1319+
return g.eval_comptime_cond(cond.lhs) || g.eval_comptime_cond(cond.rhs)
1320+
}
1321+
}
1322+
ast.PostfixExpr {
1323+
// Handle optional feature check: feature?
1324+
if cond.op == .question {
1325+
if cond.expr is ast.Ident {
1326+
return g.eval_comptime_flag(cond.expr.name)
1327+
}
1328+
}
1329+
}
1330+
ast.ParenExpr {
1331+
return g.eval_comptime_cond(cond.expr)
1332+
}
1333+
else {}
1334+
}
1335+
return false
1336+
}
1337+
1338+
// eval_comptime_flag evaluates a single comptime flag/identifier
1339+
fn (g Gen) eval_comptime_flag(name string) bool {
1340+
// OS checks - use comptime conditionals with direct returns
1341+
match name {
1342+
'macos', 'darwin' {
1343+
$if macos {
1344+
return true
1345+
}
1346+
return false
1347+
}
1348+
'linux' {
1349+
$if linux {
1350+
return true
1351+
}
1352+
return false
1353+
}
1354+
'windows' {
1355+
$if windows {
1356+
return true
1357+
}
1358+
return false
1359+
}
1360+
'freebsd' {
1361+
$if freebsd {
1362+
return true
1363+
}
1364+
return false
1365+
}
1366+
'posix', 'unix' {
1367+
$if macos {
1368+
return true
1369+
} $else $if linux {
1370+
return true
1371+
} $else $if freebsd {
1372+
return true
1373+
}
1374+
return false
1375+
}
1376+
// Architecture checks
1377+
'amd64', 'x86_64' {
1378+
$if amd64 {
1379+
return true
1380+
}
1381+
return false
1382+
}
1383+
'arm64', 'aarch64' {
1384+
$if arm64 {
1385+
return true
1386+
}
1387+
return false
1388+
}
1389+
'x86' {
1390+
// x86 (32-bit) is rarely used in modern systems
1391+
return false
1392+
}
1393+
// Common feature flags (typically false in simple compilers)
1394+
'freestanding', 'ios', 'android', 'termux', 'debug', 'test' {
1395+
return false
1396+
}
1397+
else {
1398+
// Unknown flag - default to false
1399+
return false
1400+
}
1401+
}
1402+
}
1403+
12591404
fn (mut g Gen) write_indent() {
12601405
for _ in 0 .. g.indent {
12611406
g.sb.write_string('\t')

0 commit comments

Comments
 (0)