编译生成C代码

编译器本质上就是一门语言生成另一门语言的过程

V目前的编译思路是:编译生成对应的C代码,然后调用C编译器来生成可执行文件

V语言的开发重点在编译器前端,C就是编译器后端

现在也生成了js代码,估计也会生成wasm代码

或者考虑基于LLVM,生成LLVM IR

或者直接生成机器码


生成C代码

使用-o参数就可以

把当前目录的main.v代码生成main.c代码:

  1. v -o main.c ./main.v

通过查看V代码生成的C代码,可以更容易理解V编译器是如何编译的

基本类型对应

v的基本类型通过C的类型别名typedef来实现

  1. //int类型没有类型别名,直接就是C的int类型
  2. typedef int64_t i64;
  3. typedef int16_t i16;
  4. typedef int8_t i8;
  5. typedef uint64_t u64;
  6. typedef uint32_t u32;
  7. typedef uint16_t u16;
  8. typedef uint8_t byte;
  9. typedef uint32_t rune;
  10. typedef float f32;
  11. typedef double f64;
  12. typedef unsigned char* &byte; //字节指针
  13. typedef int* intptr; //整型指针
  14. typedef void* voidptr; //通用指针
  15. typedef char* charptr; //C字符指针
  16. typedef struct array array;
  17. typedef struct map map;
  18. typedef array array_string;
  19. typedef array array_int;
  20. typedef array array_byte;
  21. typedef array array_f32;
  22. typedef array array_f64;
  23. typedef array array_u16;
  24. typedef array array_u32;
  25. typedef array array_u64;
  26. typedef map map_int;
  27. typedef map map_string;
  28. typedef byte array_fixed_byte_300 [300];
  29. typedef byte array_fixed_byte_400 [400];
  30. typedef uint8_t byte;
  31. ...
  32. #ifndef bool
  33. typedef int bool; //布尔类型在C里面通过int类型来实现,1字节
  34. typedef byte bool;
  35. #define true 1 //true是整数常量1
  36. #define false 0 //false是整数常量0
  37. #endif

代码对照表

常量

int类型常量,生成C的宏定义:

  1. //V代码
  2. const (
  3. i=1 //int类型的常量
  4. )
  5. //C代码
  6. #define _const_i 1 //整数类型的常量通过C宏定义

其他类型常量,生成C的全局变量,常量的不可修改,由V编译器负责检查

这样就很好理解,V语言中的常量可以是任何类型,跟变量一样,甚至可以是函数调用的结果

  1. //V代码
  2. const (
  3. a=i8(11)
  4. b=i16(12)
  5. c=i64(13)
  6. d=byte(14)
  7. e=u16(15)
  8. f=u32(16)
  9. g=u64(17)
  10. h=f32(1.1)
  11. i=f64(1.2)
  12. bb=true
  13. )
  14. //C代码
  15. i8 _const_a; // inited later
  16. i16 _const_b; // inited later
  17. i64 _const_c; // inited later
  18. byte _const_d; // inited later
  19. u16 _const_e; // inited later
  20. u32 _const_f; // inited later
  21. u64 _const_g; // inited later
  22. f32 _const_h; // inited later
  23. f64 _const_i; // inited later
  24. bool _const_bb; // inited later
  25. void _vinit() { //然后在_vinit函数进行初始化
  26. _const_a = ((i8)(11));
  27. _const_b = ((i16)(12));
  28. _const_c = ((i64)(13));
  29. _const_d = ((byte)(14));
  30. _const_e = ((u16)(15));
  31. _const_f = ((u32)(16));
  32. _const_g = ((u64)(17));
  33. _const_h = ((f32)(1.1));
  34. _const_i = ((f64)(1.2));
  35. _const_bb = true;
  36. }

枚举

  1. //V代码
  2. pub enum Color {
  3. blue =1 //如果没有指定初始值,默认从0开始,然后往下递增1
  4. green
  5. white
  6. black
  7. }
  8. c := Color.blue
  9. //C代码
  10. typedef enum {
  11. Color_blue = 1 ,
  12. Color_green, // 1
  13. Color_white, // 2
  14. Color_black, // 3
  15. } Color;
  16. Color c = Color_blue;

模块

V的模块,在生成对应C代码后,只是对应元素名称的前缀,毕竟C语言中没有模块的概念

常量,结构体,接口,类型等一级元素生成C代码后的名称规则是:”模块名__名称”,用双下划线区隔

模块中的add()函数生成C代码后的名称为:mymodule__add()

结构体的方法等二级元素生成C代码后的名称规则是:”模块名 _ 类名 方法名”,用单下划线区隔

例模块中的Color结构体的str()方法生成C代码后的名称为:mymodule__Color_str()

函数

主模块中的主函数和函数,生成等价的C的函数

  1. //V代码
  2. module main
  3. fn main() {
  4. println('from main')
  5. add(1,3)
  6. }
  7. pub fn add(x,y int) int { //pub的模块访问控制由V编译器负责检查,C没有pub的对应
  8. if x>0 {
  9. return x+y
  10. } else {
  11. return x+y
  12. }
  13. }
  14. //C代码
  15. int add(int x, int y); //函数声明
  16. int main(int ___argc, char** ___argv) { //主函数生成主函数
  17. _vinit(); //先执行初始化函数
  18. println(tos3("from main"));
  19. add(1, 3);
  20. return 0;
  21. }
  22. int add(int x, int y) {
  23. if (x > 0) {
  24. return x + y;
  25. } else {
  26. return x + y;
  27. }
  28. }

函数defer语句

C没有defer语句,V编译的时候就是把函数中的defer语句去掉,然后按后进先出的顺序放在defer语句之后的所有return语句前以及函数末尾,有各自独立的代码块

  1. //V代码
  2. fn main(){
  3. defer {defer_fn1()}
  4. defer {defer_fn2()}
  5. println('main start')
  6. if 1<2 {
  7. return
  8. }
  9. if 1==1 {
  10. return
  11. }
  12. println('main end')
  13. }
  14. fn defer_fn1(){
  15. println('from defer_fn1')
  16. }
  17. fn defer_fn2(){
  18. println('from defer_fn2')
  19. }
  20. //C代码
  21. int main(int ___argc, char** ___argv) {
  22. _vinit();
  23. println(tos3("main start"));
  24. if (1 < 2) {
  25. // defer
  26. defer_fn1();//defer语句之后的所有return语句之前
  27. // defer
  28. defer_fn2();//defer语句之后的所有return语句之前
  29. return 0;
  30. }
  31. if (1 == 1) {
  32. // defer
  33. defer_fn1();//defer语句之后的所有return语句之前
  34. // defer
  35. defer_fn2();//defer语句之后的所有return语句之前
  36. return 0;
  37. }
  38. println(tos3("main end"));
  39. // defer
  40. defer_fn1();//函数末尾
  41. // defer
  42. defer_fn2();//函数末尾
  43. return 0;
  44. }
  45. void defer_fn1() {
  46. println(tos3("from defer_fn1"));
  47. }
  48. void defer_fn2() {
  49. println(tos3("from defer_fn2"));
  50. }

函数不确定个数参数

不确定参数就是根据返回值的类型和调用的最大参数数量,编译时动态生成一个结构体

然后把最后一个参数变为这个结构体的指针类型

不确定参数结构体,会重用,如果有别的函数也是返回了相同类型的不确定参数,会直接使用,同时修改args数组的长度为调用过参数的最大值

  1. //V代码
  2. fn my_fn(i int,s string, others ...string) {
  3. println(i)
  4. println(s)
  5. println(others[0])
  6. println(others[1])
  7. println(others[2])
  8. }
  9. fn main() {
  10. my_fn(1,'abc','de','fg','hi')
  11. }
  12. //C代码
  13. struct varg_string { //自动生成不确定参数结构体
  14. int len;
  15. string args[4];
  16. };
  17. void main__my_fn(int i, string s, varg_string *others) {
  18. printf("%d\n", i);
  19. println(s);
  20. println(others->args[0]);
  21. println(others->args[1]);
  22. println(others->args[2]);
  23. }
  24. void main__main() {
  25. main__my_fn(
  26. 1, tos3("abc"),
  27. &(varg_string){.len = 3, .args = {tos3("de"), tos3("fg"), tos3("hi")}});
  28. }

函数多返回值

C的函数返回值只有1个,V的函数多返回值,就是把多返回值的组合,编译时动态生成一个结构体,然后返回结构体

  1. //V代码
  2. fn foo() (int, int) { //多返回值
  3. return 2, 3
  4. }
  5. fn some_multiret_fn(a int, b int) (int, int) {
  6. return a+1, b+1 //可以返回表达式
  7. }
  8. fn main() {
  9. a, b := foo()
  10. println(a) // 2
  11. println(b) // 3
  12. }
  13. //C代码
  14. typedef struct _V_MulRet_int_V_int _V_MulRet_int_V_int;
  15. struct _V_MulRet_int_V_int { //生成的返回值组合的结构体,还可以给其他函数共用
  16. int var_0;
  17. int var_1;
  18. };
  19. _V_MulRet_int_V_int main__foo() {
  20. return (_V_MulRet_int_V_int){.var_0 = 2, .var_1 = 3};
  21. }
  22. _V_MulRet_int_V_int main__some_multiret_fn(int a, int b) {
  23. return (_V_MulRet_int_V_int){.var_0 = a + 1, .var_1 = b + 1};
  24. }
  25. void main__main() {
  26. _V_MulRet_int_V_int _V_mret_49_a_b = main__foo();
  27. int a = _V_mret_49_a_b.var_0;
  28. int b = _V_mret_49_a_b.var_1;
  29. /*opt*/ printf("%d\n", a);
  30. /*opt*/ printf("%d\n", b);
  31. }

数组

V的数组是用struct来实现的,生成C代码也是struct

  1. //V代码
  2. fn main() {
  3. a:=[1,3,5]
  4. b:=['a','b','c']
  5. println(a)
  6. println(b)
  7. }
  8. //C代码
  9. //第一部分: 从内置的vlib/built/array.v生成
  10. struct array {
  11. void* data;
  12. int len;
  13. int cap;
  14. int element_size;
  15. };
  16. //第二部分:从内置的vlib/built/array.v生成
  17. typedef struct array array;
  18. typedef array array_string;
  19. typedef array array_int;
  20. typedef array array_byte;
  21. typedef array array_f32;
  22. typedef array array_f64;
  23. typedef array array_u16;
  24. typedef array array_u32;
  25. typedef array array_u64;
  26. //第三部分:数组使用的代码,字面量方式创建
  27. array_int a=new_array_from_c_array(3, 3, sizeof(int), EMPTY_ARRAY_OF_ELEMS( int, 3 ) { 1 , 3 , 5 }) ;
  28. array_string b=new_array_from_c_array(3, 3, sizeof(string), EMPTY_ARRAY_OF_ELEMS( string, 3 ) { tos3("a") , tos3("b") , tos3("c") }) ;
  29. println (array_int_str( a ) ) ;
  30. println (array_string_str( b ) ) ;
  31. }

字符串

V的字符串是用struct来实现的,生成C代码也是struct

  1. //V代码
  2. //vlib/builtin/string.v
  3. pub struct string {
  4. // var:
  5. // hash_cache int
  6. pub:
  7. str &byte // points to a C style 0 terminated string of bytes.
  8. len int // the length of the .str field, excluding the ending 0 byte. It is always equal to strlen(.str).
  9. }
  10. //string的各种内置方法:
  11. ...
  12. //使用代码:
  13. fn main(){
  14. mystr:='abc'
  15. mystr2:="def"
  16. println(mystr)
  17. println(mystr2)
  18. }
  19. //C代码
  20. //第一部分:vlib/builtin/string.v生成:
  21. typedef struct string string;
  22. struct string {
  23. byte* str;
  24. int len;
  25. };
  26. //string的各种内置方法生成:
  27. string string_left (string s, int n);
  28. string string_right (string s, int n);
  29. string string_substr2 (string s, int start, int _end, bool end_max);
  30. string string_substr (string s, int start, int end);
  31. //第二部分,使用代码:
  32. void main__main () {
  33. string mystr= tos3("abc") ;
  34. string mystr2= tos3("def") ;
  35. println ( mystr ) ;
  36. println ( mystr2 ) ;
  37. }

字典

V的字典是用struct来实现的,生成C代码也是struct

  1. //V代码
  2. //第一部分:定义map
  3. pub struct map {
  4. element_size int
  5. root &mapnode
  6. pub:
  7. size int
  8. }
  9. struct mapnode {
  10. left &mapnode
  11. right &mapnode
  12. is_empty bool // set by delete()
  13. key string
  14. val voidptr
  15. }
  16. //其他map内置方法
  17. ...
  18. //第二部分:使用map
  19. fn main() {
  20. mut m := map[string]int
  21. m['one'] = 1
  22. m['two'] = 2
  23. println(m['one'])
  24. println(m['bad_key'])
  25. }
  26. //C代码
  27. //第一部分:定义map
  28. typedef struct map map;
  29. typedef struct mapnode mapnode;
  30. typedef map map_int;
  31. typedef map map_string;
  32. struct map {
  33. int element_size;
  34. mapnode* root;
  35. int size;
  36. };
  37. struct mapnode {
  38. mapnode* left;
  39. mapnode* right;
  40. bool is_empty;
  41. string key;
  42. void* val;
  43. };
  44. //map的各种内置方法
  45. ...
  46. //第二部分:使用map:
  47. void main__main () {
  48. map_int m= new_map(1, sizeof(int)) ;
  49. map_set(& m , tos3("one") , & (int []) { 1 }) ;
  50. map_set(& m , tos3("two") , & (int []) { 2 }) ;
  51. int tmp1 = 0; bool tmp2 = map_get(m , tos3("one"), & tmp1);
  52. printf ("%d\n", tmp1 ) ;
  53. int tmp3 = 0; bool tmp4 = map_get(m , tos3("bad_key"), & tmp3);
  54. printf ("%d\n", tmp3 ) ;
  55. }

结构体

生成对应的C结构体

  1. //V代码
  2. pub struct Point {
  3. x int
  4. y int
  5. }
  6. pub fn (p Point) str() string {
  7. return 'x is ${p.x},y is:${p.y}'
  8. }
  9. fn main() {
  10. p := Point{
  11. x: 1
  12. y: 3
  13. }
  14. println(p)
  15. }
  16. //C代码
  17. struct Point {
  18. int x;
  19. int y;
  20. };
  21. string Point_str (Point p); //函数声明
  22. string Point_str (Point p) { //函数定义,默认第一个参数是自己
  23. return _STR("x is %d,y is:%d", p .x, p .y) ;
  24. }
  25. void main__main () {
  26. Point p= (Point) { .x = 1 , .y = 3 } ;
  27. println (Point_str( p ) ) ;
  28. }

结构体方法

生成对应的C函数,默认第一个参数是对应的结构体类型的指针

生成的C函数的命名规则是:”结构体名_方法名”

  1. //V代码
  2. pub fn (mut a array) insert(i int, val voidptr) {
  3. if i < 0 || i > a.len {
  4. panic('array.insert: index out of range (i == $i, a.len == $a.len)')
  5. }
  6. a.ensure_cap(a.len + 1)
  7. size := a.element_size
  8. C.memmove(a.data + (i + 1) * size, a.data + i * size, (a.len - i) * size)
  9. C.memcpy(a.data + i * size, val, size)
  10. a.len++
  11. }
  12. //C代码
  13. void array_insert(array *a, int i, void *val) { //默认第一个参数是对应类型指针
  14. if (i < 0 || i > a->len) {
  15. v_panic(_STR("array.insert: index out of range (i == %d, a.len == %d)", i,
  16. a->len));
  17. };
  18. array_ensure_cap(a, a->len + 1);
  19. int size = a->element_size;
  20. memmove((byte *)a->data + (i + 1) * size, (byte *)a->data + i * size,
  21. (a->len - i) * size);
  22. memcpy((byte *)a->data + i * size, val, size);
  23. a->len++;
  24. }

结构体访问控制

访问控制在C代码中没有体现,全部在V编译器中控制

  1. //V代码
  2. struct Foo {
  3. a int //私有,不可变(默认).在模块内部可访问,不可修改;模块外不可访问,不可修改
  4. mut:
  5. b int // 私有,可变.在模块内部可访问,可修改,模块外部不可访问,不可修改
  6. c int // (相同访问控制的字段可以放在一起)
  7. pub:
  8. d int // 公共,不可变,只读.在模块内部和外部都可以访问,但是不可修改
  9. pub mut:
  10. e int //公共,模块内部可访问,可修改;模块外部可访问,但是不可修改
  11. __global:
  12. f int // 全局字段,模块内部和外部都可访问,可修改,这样等于破坏了封装性,不推荐使用
  13. }
  14. fn main() {
  15. f:=Foo{}
  16. println(f)
  17. }
  18. //C代码
  19. typedef struct Foo Foo;
  20. struct Foo {
  21. int a;
  22. int b;
  23. int c;
  24. int d;
  25. int e;
  26. int f;
  27. };
  28. string Foo_str();
  29. void main__main() {
  30. Foo f = (Foo){.a = 0, .b = 0, .c = 0, .d = 0, .e = 0, .f = 0};
  31. println(Foo_str(f));
  32. }
  33. string Foo_str(Foo a) {
  34. return _STR("{\n a: %d\n b: %d\n c: %d\n d: %d\n e: %d\n f: %d\n}", a.a,a.b, a.c, a.d, a.e, a.f);
  35. }

流程控制语句

if语句,生成C if语句

  1. //V代码
  2. fn main() {
  3. a := 10
  4. b := 20
  5. if a < b {
  6. println('$a < $b')
  7. }
  8. else if a > b {
  9. println('$a > $b')
  10. }
  11. else {
  12. println('$a == $b')
  13. }
  14. }
  15. //C代码
  16. void main__main () {
  17. int a= 10 ;
  18. int b= 20 ;
  19. if ( a < b ) {
  20. printf( "%d < %d\n", a, b ) ;
  21. }
  22. else if ( a > b ) {
  23. printf( "%d > %d\n", a, b ) ;
  24. }
  25. else {
  26. printf( "%d == %d\n", a, b ) ;
  27. }

if表达式语句,生成C的三元运算符 ? :

  1. //V代码
  2. fn main() {
  3. num := 777
  4. s := if num % 2 == 0 {
  5. 'even'
  6. }
  7. else {
  8. 'odd'
  9. }
  10. println(s) // "odd"
  11. }
  12. //C代码
  13. void main__main() {
  14. int num = 777;
  15. string s = ((num % 2 == 0) ? (tos3("even")) : (tos3("odd")));
  16. println(s);
  17. }

match语句

  1. //V代码
  2. fn main() {
  3. os:='macos'
  4. match os {
  5. 'windows' {
  6. println('windows')
  7. }
  8. 'linux' {
  9. println('linux')
  10. }
  11. 'macos' {
  12. println('macos')
  13. }
  14. else {
  15. println('unknow')
  16. }
  17. }
  18. }
  19. //C代码
  20. void main__main() {
  21. string os = tos3("macos");
  22. string tmp1 = os;
  23. if (string_eq(tmp1, tos3("windows"))) {
  24. println(tos3("windows"));
  25. } else if (string_eq(tmp1, tos3("linux"))) {
  26. println(tos3("linux"));
  27. } else if (string_eq(tmp1, tos3("macos"))) {
  28. println(tos3("macos"));
  29. } else // default:
  30. {
  31. println(tos3("unknow"));
  32. };
  33. }

match表达式语句

  1. //V代码
  2. fn main() {
  3. os:='macos'
  4. price:=match os {
  5. 'windows' {
  6. 100
  7. }
  8. 'linux' {
  9. 120
  10. }
  11. 'macos' {
  12. 150
  13. }
  14. else {
  15. 0
  16. }
  17. }
  18. println(price) //输出150
  19. }
  20. //C代码
  21. //生成嵌套的三元表达式
  22. void main__main() {
  23. string os = tos3("macos");
  24. string tmp1 = os;
  25. int price = ((string_eq(tmp1, tos3("windows")))
  26. ? (100)
  27. : ((string_eq(tmp1, tos3("linux")))
  28. ? (120)
  29. : ((string_eq(tmp1, tos3("macos"))) ? (150) : (0))));
  30. /*opt*/ printf("%d\n", price);
  31. }

for循环

传统的:for i=0;i<100;i++ {}

  1. //V代码
  2. fn main() {
  3. for i := 0; i < 10; i++ {
  4. //跳过6
  5. if i == 6 {
  6. continue
  7. }
  8. println(i)
  9. }
  10. }
  11. //C代码
  12. void main__main() {
  13. for (int i = 0; i < 10; i++) {
  14. if (i == 6) {
  15. continue;
  16. };
  17. /*opt*/ printf("%d\n", i);
  18. };
  19. }

替代while:for i<100 {}

  1. //V代码
  2. fn main() {
  3. mut sum := 0
  4. mut i := 0
  5. for i <= 100 {
  6. sum += i
  7. i++
  8. }
  9. println(sum) // 输出"5050"
  10. }
  11. //C代码
  12. void main__main () {
  13. int sum= 0 ;
  14. int i= 0 ;
  15. while ( i <= 100 ) {
  16. sum += i ;
  17. i ++ ;
  18. }

无限循环:for {}

  1. //V代码
  2. fn main() {
  3. mut num := 0
  4. for {
  5. num++
  6. if num >= 10 {
  7. break
  8. }
  9. }
  10. println(num) // "10"
  11. }
  12. //C代码
  13. void main__main() {
  14. int num = 0;
  15. while (1) {
  16. num++;
  17. if (num >= 10) {
  18. break;
  19. };
  20. };
  21. /*opt*/ printf("%d\n", num);
  22. }

遍历:for i in xxx {}

  1. //V代码
  2. fn main() {
  3. numbers := [1, 2, 3, 4, 5]
  4. for i,num in numbers {
  5. println('i:$i,num:$num')
  6. }
  7. }
  8. //C代码
  9. void main__main() {
  10. array_int numbers = new_array_from_c_array(
  11. 5, 5, sizeof(int), EMPTY_ARRAY_OF_ELEMS(int, 5){1, 2, 3, 4, 5});
  12. array_int tmp1 = numbers;
  13. for (int i = 0; i < tmp1.len; i++) {
  14. int num = ((int *)tmp1.data)[i];
  15. printf("i:%d,num:%d\n", i, num);
  16. };
  17. }

类型定义

类型定义type生成C的类型别名typedef

  1. //V代码
  2. pub struct Point {
  3. x int
  4. y int
  5. }
  6. type myint=int
  7. type myPoint=Point
  8. //C代码
  9. struct Point {
  10. int x;
  11. int y;
  12. };
  13. typedef int myint;
  14. typedef Point myPoint;

接口

  1. //V代码
  2. //C代码

泛型

  1. //V代码
  2. //C代码

错误处理

  1. //V代码
  2. //C代码

联合类型

  1. //V代码
  2. struct User {
  3. name string
  4. age int
  5. }
  6. pub fn (m &User) str() string {
  7. return 'name:$m.name,age:$m.age'
  8. }
  9. type MySum= int|string|User //联合类型声明
  10. i:=123
  11. s:='abc'
  12. u:=User{name:'tom',age:33}
  13. mut res:=MySum{} //声明联合类型变量
  14. res=i
  15. res=s
  16. res=u
  17. pub fn add(ms MySum) {
  18. match ms {
  19. int {
  20. println('ms is int,value is $it.str()')
  21. }
  22. string {
  23. println('ms is string,value is $it')
  24. }
  25. User {
  26. println('ms is User,value is $it.str()')
  27. }
  28. else {
  29. println('unknown')
  30. }
  31. }
  32. }
  33. //C代码
  34. #define SumType_int 1 // DEF2
  35. #define SumType_string 2 // DEF2
  36. #define SumType_User 3 // DEF2
  37. typedef struct {
  38. void *obj; //存储变量指针
  39. int typ; //联合类型中对应的类型常量,就是上面的宏定义
  40. } MySum;
  41. //声明联合类型变量
  42. MySum res = (MySum){EMPTY_STRUCT_INITIALIZATION};
  43. //变量赋值
  44. res = /*SUM TYPE CAST2*/ (MySum){.obj = memdup(&(int[]){i}, sizeof(int)),
  45. .typ = SumType_int};
  46. res = /*SUM TYPE CAST2*/ (MySum){.obj = memdup(&(string[]){s}, sizeof(string)), .typ = SumType_string};
  47. res = /*SUM TYPE CAST2*/ (MySum){.obj = memdup(&(User[]{u},sizeof(User)),
  48. .typ = SumType_User};
  49. //match类型判断
  50. if (tmp3.typ == SumType_int) {
  51. int *it = (int *)tmp3.obj;
  52. printf("res is:%.*s\n", int_str(*it).len, int_str(*it).str);
  53. } else if (tmp3.typ == SumType_string) {
  54. string *it = (string *)tmp3.obj;
  55. printf("res is:%p\n", it);
  56. } else if (tmp3.typ == SumType_User) {
  57. User *it = (User *)tmp3.obj;
  58. printf("res is:%.*s\n", User_str(&/* ? */ *it).len,
  59. User_str(&/* ? */ *it).str);
  60. } else // default:
  61. {
  62. println(tos3("unknown"));
  63. };

运算符重载

  1. //V代码
  2. //C代码

条件编译

生成等价的C宏定义

  1. //V代码
  2. fn main() {
  3. $if windows {
  4. println('windows')
  5. }
  6. $if linux {
  7. println('linux')
  8. }
  9. $if macos {
  10. println('mac')
  11. }
  12. }
  13. //C代码
  14. VV_LOCAL_SYMBOL void main__main() {
  15. #if defined(_WIN32)
  16. {
  17. }
  18. #endif
  19. #if defined(__linux__)
  20. {
  21. }
  22. #endif
  23. #if defined(__APPLE__)
  24. {
  25. println(tos_lit("mac"));
  26. }
  27. #endif
  28. }
  1. //V代码
  2. fn main() {
  3. mut x := 0
  4. $if x32 {
  5. println('system is 32 bit')
  6. x = 1
  7. }
  8. $if x64 {
  9. println('system is 64 bit')
  10. x = 2
  11. }
  12. }
  13. //C代码
  14. void main__main() {
  15. int x = 0;
  16. #ifdef TARGET_IS_32BIT
  17. println(tos3("system is 32 bit"));
  18. x = 1;
  19. #endif
  20. ;
  21. #ifdef TARGET_IS_64BIT
  22. println(tos3("system is 64 bit"));
  23. x = 2;
  24. #endif
  25. ;
  1. //V代码
  2. fn main() {
  3. mut x := 0
  4. $if little_endian {
  5. println('system is little endian')
  6. x = 1
  7. }
  8. $if big_endian {
  9. println('system is big endian')
  10. x = 2
  11. }
  12. }
  13. //C代码
  14. void main__main() {
  15. int x = 0;
  16. #ifdef TARGET_ORDER_IS_LITTLE
  17. println(tos3("system is little endian"));
  18. x = 1;
  19. #endif
  20. ;
  21. #ifdef TARGET_ORDER_IS_BIG
  22. println(tos3("system is big endian"));
  23. x = 2;
  24. #endif
  25. ;

内联汇编代码

生成等价的C内联汇编的代码

  1. //V代码
  2. fn main() {
  3. a := 10
  4. b := 0
  5. unsafe { //unsafe代码块
  6. asm { //asm代码块,里面可以直接写汇编代码
  7. "movl %1, %%eax;"
  8. "movl %%eax, %0;"
  9. :"=r"(b)
  10. :"r"(a)
  11. :"%eax"
  12. }
  13. }
  14. println(a) //返回10
  15. println(b) //返回10,直接通过汇编代码修改了b的值
  16. e := 0
  17. unsafe {
  18. asm {
  19. "movl $5, %0"
  20. :"=a"(e)
  21. }
  22. }
  23. println(e) //返回5,直接通过汇编代码修改了e的值
  24. }
  25. //C代码
  26. void main__main() {
  27. int a = 10;
  28. int b = 0;
  29. {
  30. asm("movl %1, %%eax;"
  31. "movl %%eax, %0;"
  32. : "=r"(b)
  33. : "r"(a)
  34. : "%eax");
  35. ;
  36. };
  37. /*opt*/ printf("%d\n", a);
  38. /*opt*/ printf("%d\n", b);
  39. int e = 0;
  40. {
  41. asm("movl $5, %0" : "=a"(e));
  42. ;
  43. };
  44. /*opt*/ printf("%d\n", e);
  45. }