Watch one program become machine work.

Follow a real program through five compiler stages, from source to result, then run your own in Venutian's own compiler.

The stepper

Follow one program through Source, Tokens, Syntax tree, Bytecode and Result. Every panel shows real output captured from the compiler at build time.

hello hello.ven
  1. Source

    The program exactly as it sits in the file, the text the compiler reads.
    print "Hello from Venutian"
  2. Tokens

    The venutian tokens command cuts that text into words, each with its kind, its value, its line and its column.
    1. PRINTprintline 1 column 1
    2. TEXT"Hello from Venutian"line 1 column 7
    3. NEWLINEline 1 column 28
    4. EOFline 3 column 1
  3. Syntax tree

    The venutian ast command shows the grammar the parser found: every statement a node, every name and literal a leaf.
    • Program
      • statements
        • PrintStatement
          • args
            • TextLiteral value "Hello from Venutian"
  4. Bytecode

    The venutian disasm command lists the instructions the virtual machine runs, each operand resolved to the constant it names.
    main
    OffsetInstructionOperandConstant
    0LOAD_CONST0"Hello from Venutian"
    1PRINT1
    2HALT
  5. Output

    The venutian run command compiles the program and runs it on the native virtual machine, and this is what it printed.
    Hello from Venutian

    exit 0

grade guards.ven
  1. Source

    The program exactly as it sits in the file, the text the compiler reads.
    make grade(score)    choose score        is n: Integer where n >= 90            give "A"        is n: Integer where n >= 80            give "B"        is n: Integer where n >= 70            give "C"        is : Integer            give "F"        otherwise            give "not a number"print grade(95)print grade(82)print grade(71)print grade(50)print grade("ninety")
  2. Tokens

    The venutian tokens command cuts that text into words, each with its kind, its value, its line and its column.
    1. MAKEmakeline 1 column 1
    2. IDENTgradeline 1 column 6
    3. LPAREN(line 1 column 11
    4. IDENTscoreline 1 column 12
    5. RPAREN)line 1 column 17
    6. NEWLINEline 1 column 18
    7. INDENT4line 2 column 1
    8. CHOOSEchooseline 2 column 5
    9. IDENTscoreline 2 column 12
    10. NEWLINEline 2 column 17
    11. INDENT8line 3 column 1
    12. ISisline 3 column 9
    13. IDENTnline 3 column 12
    14. COLON:line 3 column 13
    15. IDENTIntegerline 3 column 15
    16. WHEREwhereline 3 column 23
    17. IDENTnline 3 column 29
    18. GE>=line 3 column 31
    19. INTEGER90line 3 column 34
    20. NEWLINEline 3 column 36
    21. INDENT12line 4 column 1
    22. GIVEgiveline 4 column 13
    23. TEXT"A"line 4 column 18
    24. NEWLINEline 4 column 21
    25. DEDENT8line 5 column 1
    26. ISisline 5 column 9
    27. IDENTnline 5 column 12
    28. COLON:line 5 column 13
    29. IDENTIntegerline 5 column 15
    30. WHEREwhereline 5 column 23
    31. IDENTnline 5 column 29
    32. GE>=line 5 column 31
    33. INTEGER80line 5 column 34
    34. NEWLINEline 5 column 36
    35. INDENT12line 6 column 1
    36. GIVEgiveline 6 column 13
    37. TEXT"B"line 6 column 18
    38. NEWLINEline 6 column 21
    39. DEDENT8line 7 column 1
    40. ISisline 7 column 9
    41. IDENTnline 7 column 12
    42. COLON:line 7 column 13
    43. IDENTIntegerline 7 column 15
    44. WHEREwhereline 7 column 23
    45. IDENTnline 7 column 29
    46. GE>=line 7 column 31
    47. INTEGER70line 7 column 34
    48. NEWLINEline 7 column 36
    49. INDENT12line 8 column 1
    50. GIVEgiveline 8 column 13
    51. TEXT"C"line 8 column 18
    52. NEWLINEline 8 column 21
    53. DEDENT8line 9 column 1
    54. ISisline 9 column 9
    55. COLON:line 9 column 12
    56. IDENTIntegerline 9 column 14
    57. NEWLINEline 9 column 21
    58. INDENT12line 10 column 1
    59. GIVEgiveline 10 column 13
    60. TEXT"F"line 10 column 18
    61. NEWLINEline 10 column 21
    62. DEDENT8line 11 column 1
    63. OTHERWISEotherwiseline 11 column 9
    64. NEWLINEline 11 column 18
    65. INDENT12line 12 column 1
    66. GIVEgiveline 12 column 13
    67. TEXT"not a number"line 12 column 18
    68. NEWLINEline 12 column 32
    69. DEDENT0line 14 column 1
    70. DEDENT0line 14 column 1
    71. DEDENT0line 14 column 1
    72. PRINTprintline 14 column 1
    73. IDENTgradeline 14 column 7
    74. LPAREN(line 14 column 12
    75. INTEGER95line 14 column 13
    76. RPAREN)line 14 column 15
    77. NEWLINEline 14 column 16
    78. PRINTprintline 15 column 1
    79. IDENTgradeline 15 column 7
    80. LPAREN(line 15 column 12
    81. INTEGER82line 15 column 13
    82. RPAREN)line 15 column 15
    83. NEWLINEline 15 column 16
    84. PRINTprintline 16 column 1
    85. IDENTgradeline 16 column 7
    86. LPAREN(line 16 column 12
    87. INTEGER71line 16 column 13
    88. RPAREN)line 16 column 15
    89. NEWLINEline 16 column 16
    90. PRINTprintline 17 column 1
    91. IDENTgradeline 17 column 7
    92. LPAREN(line 17 column 12
    93. INTEGER50line 17 column 13
    94. RPAREN)line 17 column 15
    95. NEWLINEline 17 column 16
    96. PRINTprintline 18 column 1
    97. IDENTgradeline 18 column 7
    98. LPAREN(line 18 column 12
    99. TEXT"ninety"line 18 column 13
    100. RPAREN)line 18 column 21
    101. NEWLINEline 18 column 22
    102. EOFline 20 column 1
  3. Syntax tree

    The venutian ast command shows the grammar the parser found: every statement a node, every name and literal a leaf.
    • Program
      • statements
        • FunctionDecl name grade
          • params
            • Param name score
          • body
            • ChooseStatement
              • subject
                • Name identifier score
              • branches
                • ChooseBranch
                  • pattern
                    • TypePattern var_name n type_name Integer
                  • body
                    • GiveStatement
                      • value
                        • TextLiteral value "A"
                  • guard
                    • BinaryOp op >=
                      • left
                        • Name identifier n
                      • right
                        • IntegerLiteral value 90
                • ChooseBranch
                  • pattern
                    • TypePattern var_name n type_name Integer
                  • body
                    • GiveStatement
                      • value
                        • TextLiteral value "B"
                  • guard
                    • BinaryOp op >=
                      • left
                        • Name identifier n
                      • right
                        • IntegerLiteral value 80
                • ChooseBranch
                  • pattern
                    • TypePattern var_name n type_name Integer
                  • body
                    • GiveStatement
                      • value
                        • TextLiteral value "C"
                  • guard
                    • BinaryOp op >=
                      • left
                        • Name identifier n
                      • right
                        • IntegerLiteral value 70
                • ChooseBranch
                  • pattern
                    • TypePattern type_name Integer
                  • body
                    • GiveStatement
                      • value
                        • TextLiteral value "F"
                • ChooseBranch
                  • body
                    • GiveStatement
                      • value
                        • TextLiteral value "not a number"
        • PrintStatement
          • args
            • Call
              • callee
                • Name identifier grade
              • args
                • Node 0 false
                  • 1
                    • IntegerLiteral value 95
        • PrintStatement
          • args
            • Call
              • callee
                • Name identifier grade
              • args
                • Node 0 false
                  • 1
                    • IntegerLiteral value 82
        • PrintStatement
          • args
            • Call
              • callee
                • Name identifier grade
              • args
                • Node 0 false
                  • 1
                    • IntegerLiteral value 71
        • PrintStatement
          • args
            • Call
              • callee
                • Name identifier grade
              • args
                • Node 0 false
                  • 1
                    • IntegerLiteral value 50
        • PrintStatement
          • args
            • Call
              • callee
                • Name identifier grade
              • args
                • Node 0 false
                  • 1
                    • TextLiteral value "ninety"
  4. Bytecode

    The venutian disasm command lists the instructions the virtual machine runs, each operand resolved to the constant it names.
    main
    OffsetInstructionOperandConstant
    0LOAD_CONST1395
    1CALL1 14"grade"
    2PRINT1
    3LOAD_CONST1582
    4CALL1 14"grade"
    5PRINT1
    6LOAD_CONST1671
    7CALL1 14"grade"
    8PRINT1
    9LOAD_CONST1750
    10CALL1 14"grade"
    11PRINT1
    12LOAD_CONST18"ninety"
    13CALL1 14"grade"
    14PRINT1
    15HALT
    function grade(score)
    OffsetInstructionOperandConstant
    0LOAD_NAME1"score"
    1STORE_NAME0"$choose_subject_1"
    2LOAD_NAME0"$choose_subject_1"
    3LOAD_CONST2"Integer"
    4CALL2 3"is_instance_of"
    5JUMP_IF_FALSE17
    6LOAD_NAME0"$choose_subject_1"
    7STORE_NAME4"n"
    8LOAD_NAME4"n"
    9LOAD_CONST590
    10GE
    11JUMP_IF_FALSE16
    12LOAD_CONST6"A"
    13RETURN
    14UNBIND_NAME4"n"
    15JUMP56
    16UNBIND_NAME4"n"
    17LOAD_NAME0"$choose_subject_1"
    18LOAD_CONST2"Integer"
    19CALL2 3"is_instance_of"
    20JUMP_IF_FALSE32
    21LOAD_NAME0"$choose_subject_1"
    22STORE_NAME4"n"
    23LOAD_NAME4"n"
    24LOAD_CONST780
    25GE
    26JUMP_IF_FALSE31
    27LOAD_CONST8"B"
    28RETURN
    29UNBIND_NAME4"n"
    30JUMP56
    31UNBIND_NAME4"n"
    32LOAD_NAME0"$choose_subject_1"
    33LOAD_CONST2"Integer"
    34CALL2 3"is_instance_of"
    35JUMP_IF_FALSE47
    36LOAD_NAME0"$choose_subject_1"
    37STORE_NAME4"n"
    38LOAD_NAME4"n"
    39LOAD_CONST970
    40GE
    41JUMP_IF_FALSE46
    42LOAD_CONST10"C"
    43RETURN
    44UNBIND_NAME4"n"
    45JUMP56
    46UNBIND_NAME4"n"
    47LOAD_NAME0"$choose_subject_1"
    48LOAD_CONST2"Integer"
    49CALL2 3"is_instance_of"
    50JUMP_IF_FALSE54
    51LOAD_CONST11"F"
    52RETURN
    53JUMP56
    54LOAD_CONST12"not a number"
    55RETURN
    56RETURN_NOTHING
  5. Output

    The venutian run command compiles the program and runs it on the native virtual machine, and this is what it printed.
    A
    B
    C
    F
    not a number

    exit 0

concurrency concurrency.ven
  1. Source

    The program exactly as it sits in the file, the text the compiler reads.
    :: 'spawn call_expr' starts a real OS thread running the call right now:: and returns a Task immediately, without waiting. 'await task' blocks:: until it finishes, returning its result, or re-raising its fault.make add(a, b)    give a + bt = spawn add(2, 3)print kind(t)print await t:: several tasks make genuine concurrent progressmake slow_double(n)    sleep(0.05)    give n * 2t1 = spawn slow_double(1)t2 = spawn slow_double(2)t3 = spawn slow_double(3)print await t1print await t2print await t3:: a fault inside a spawned task surfaces at 'await', not silentlymake risky()    give 1 / 0failing_task = spawn risky()attempt    await failing_taskrescue e    print "rescued:", e:: 'share'/'protect': real mutual exclusion across real threads counter = 0make increment_many(count)    i = 0    repeat while i < count        protect counter            counter = counter + 1        i = i + 1tasks = []repeat 8 times    tasks = appended(tasks, spawn increment_many(500))repeat for t in tasks    await t:: exactly 4000 (8 * 500) every time. 'protect' prevents lost updatesprint counter
  2. Tokens

    The venutian tokens command cuts that text into words, each with its kind, its value, its line and its column.
    1. MAKEmakeline 5 column 1
    2. IDENTaddline 5 column 6
    3. LPAREN(line 5 column 9
    4. IDENTaline 5 column 10
    5. COMMA,line 5 column 11
    6. IDENTbline 5 column 13
    7. RPAREN)line 5 column 14
    8. NEWLINEline 5 column 15
    9. INDENT4line 6 column 1
    10. GIVEgiveline 6 column 5
    11. IDENTaline 6 column 10
    12. PLUS+line 6 column 12
    13. IDENTbline 6 column 14
    14. NEWLINEline 6 column 15
    15. DEDENT0line 8 column 1
    16. IDENTtline 8 column 1
    17. EQ=line 8 column 3
    18. SPAWNspawnline 8 column 5
    19. IDENTaddline 8 column 11
    20. LPAREN(line 8 column 14
    21. INTEGER2line 8 column 15
    22. COMMA,line 8 column 16
    23. INTEGER3line 8 column 18
    24. RPAREN)line 8 column 19
    25. NEWLINEline 8 column 20
    26. PRINTprintline 9 column 1
    27. IDENTkindline 9 column 7
    28. LPAREN(line 9 column 11
    29. IDENTtline 9 column 12
    30. RPAREN)line 9 column 13
    31. NEWLINEline 9 column 14
    32. PRINTprintline 10 column 1
    33. AWAITawaitline 10 column 7
    34. IDENTtline 10 column 13
    35. NEWLINEline 10 column 14
    36. MAKEmakeline 13 column 1
    37. IDENTslow_doubleline 13 column 6
    38. LPAREN(line 13 column 17
    39. IDENTnline 13 column 18
    40. RPAREN)line 13 column 19
    41. NEWLINEline 13 column 20
    42. INDENT4line 14 column 1
    43. IDENTsleepline 14 column 5
    44. LPAREN(line 14 column 10
    45. NUMBER0.05line 14 column 11
    46. RPAREN)line 14 column 15
    47. NEWLINEline 14 column 16
    48. GIVEgiveline 15 column 5
    49. IDENTnline 15 column 10
    50. STAR*line 15 column 12
    51. INTEGER2line 15 column 14
    52. NEWLINEline 15 column 15
    53. DEDENT0line 17 column 1
    54. IDENTt1line 17 column 1
    55. EQ=line 17 column 4
    56. SPAWNspawnline 17 column 6
    57. IDENTslow_doubleline 17 column 12
    58. LPAREN(line 17 column 23
    59. INTEGER1line 17 column 24
    60. RPAREN)line 17 column 25
    61. NEWLINEline 17 column 26
    62. IDENTt2line 18 column 1
    63. EQ=line 18 column 4
    64. SPAWNspawnline 18 column 6
    65. IDENTslow_doubleline 18 column 12
    66. LPAREN(line 18 column 23
    67. INTEGER2line 18 column 24
    68. RPAREN)line 18 column 25
    69. NEWLINEline 18 column 26
    70. IDENTt3line 19 column 1
    71. EQ=line 19 column 4
    72. SPAWNspawnline 19 column 6
    73. IDENTslow_doubleline 19 column 12
    74. LPAREN(line 19 column 23
    75. INTEGER3line 19 column 24
    76. RPAREN)line 19 column 25
    77. NEWLINEline 19 column 26
    78. PRINTprintline 20 column 1
    79. AWAITawaitline 20 column 7
    80. IDENTt1line 20 column 13
    81. NEWLINEline 20 column 15
    82. PRINTprintline 21 column 1
    83. AWAITawaitline 21 column 7
    84. IDENTt2line 21 column 13
    85. NEWLINEline 21 column 15
    86. PRINTprintline 22 column 1
    87. AWAITawaitline 22 column 7
    88. IDENTt3line 22 column 13
    89. NEWLINEline 22 column 15
    90. MAKEmakeline 25 column 1
    91. IDENTriskyline 25 column 6
    92. LPAREN(line 25 column 11
    93. RPAREN)line 25 column 12
    94. NEWLINEline 25 column 13
    95. INDENT4line 26 column 1
    96. GIVEgiveline 26 column 5
    97. INTEGER1line 26 column 10
    98. SLASH/line 26 column 12
    99. INTEGER0line 26 column 14
    100. NEWLINEline 26 column 15
    101. DEDENT0line 28 column 1
    102. IDENTfailing_taskline 28 column 1
    103. EQ=line 28 column 14
    104. SPAWNspawnline 28 column 16
    105. IDENTriskyline 28 column 22
    106. LPAREN(line 28 column 27
    107. RPAREN)line 28 column 28
    108. NEWLINEline 28 column 29
    109. ATTEMPTattemptline 29 column 1
    110. NEWLINEline 29 column 8
    111. INDENT4line 30 column 1
    112. AWAITawaitline 30 column 5
    113. IDENTfailing_taskline 30 column 11
    114. NEWLINEline 30 column 23
    115. DEDENT0line 31 column 1
    116. RESCUErescueline 31 column 1
    117. IDENTeline 31 column 8
    118. NEWLINEline 31 column 9
    119. INDENT4line 32 column 1
    120. PRINTprintline 32 column 5
    121. TEXT"rescued:"line 32 column 11
    122. COMMA,line 32 column 21
    123. IDENTeline 32 column 23
    124. NEWLINEline 32 column 24
    125. DEDENT0line 35 column 1
    126. IDENTcounterline 35 column 7
    127. EQ=line 35 column 15
    128. INTEGER0line 35 column 17
    129. NEWLINEline 35 column 18
    130. MAKEmakeline 37 column 1
    131. IDENTincrement_manyline 37 column 6
    132. LPAREN(line 37 column 20
    133. IDENTcountline 37 column 21
    134. RPAREN)line 37 column 26
    135. NEWLINEline 37 column 27
    136. INDENT4line 38 column 1
    137. IDENTiline 38 column 5
    138. EQ=line 38 column 7
    139. INTEGER0line 38 column 9
    140. NEWLINEline 38 column 10
    141. REPEATrepeatline 39 column 5
    142. WHILEwhileline 39 column 12
    143. IDENTiline 39 column 18
    144. LT<line 39 column 20
    145. IDENTcountline 39 column 22
    146. NEWLINEline 39 column 27
    147. INDENT8line 40 column 1
    148. PROTECTprotectline 40 column 9
    149. IDENTcounterline 40 column 17
    150. NEWLINEline 40 column 24
    151. INDENT12line 41 column 1
    152. IDENTcounterline 41 column 13
    153. EQ=line 41 column 21
    154. IDENTcounterline 41 column 23
    155. PLUS+line 41 column 31
    156. INTEGER1line 41 column 33
    157. NEWLINEline 41 column 34
    158. DEDENT8line 42 column 1
    159. IDENTiline 42 column 9
    160. EQ=line 42 column 11
    161. IDENTiline 42 column 13
    162. PLUS+line 42 column 15
    163. INTEGER1line 42 column 17
    164. NEWLINEline 42 column 18
    165. DEDENT0line 44 column 1
    166. DEDENT0line 44 column 1
    167. IDENTtasksline 44 column 1
    168. EQ=line 44 column 7
    169. LBRACKET[line 44 column 9
    170. RBRACKET]line 44 column 10
    171. NEWLINEline 44 column 11
    172. REPEATrepeatline 45 column 1
    173. INTEGER8line 45 column 8
    174. TIMEStimesline 45 column 10
    175. NEWLINEline 45 column 15
    176. INDENT4line 46 column 1
    177. IDENTtasksline 46 column 5
    178. EQ=line 46 column 11
    179. IDENTappendedline 46 column 13
    180. LPAREN(line 46 column 21
    181. IDENTtasksline 46 column 22
    182. COMMA,line 46 column 27
    183. SPAWNspawnline 46 column 29
    184. IDENTincrement_manyline 46 column 35
    185. LPAREN(line 46 column 49
    186. INTEGER500line 46 column 50
    187. RPAREN)line 46 column 53
    188. RPAREN)line 46 column 54
    189. NEWLINEline 46 column 55
    190. DEDENT0line 48 column 1
    191. REPEATrepeatline 48 column 1
    192. FORforline 48 column 8
    193. IDENTtline 48 column 12
    194. INinline 48 column 14
    195. IDENTtasksline 48 column 17
    196. NEWLINEline 48 column 22
    197. INDENT4line 49 column 1
    198. AWAITawaitline 49 column 5
    199. IDENTtline 49 column 11
    200. NEWLINEline 49 column 12
    201. DEDENT0line 52 column 1
    202. PRINTprintline 52 column 1
    203. IDENTcounterline 52 column 7
    204. NEWLINEline 52 column 14
    205. EOFline 54 column 1
  3. Syntax tree

    The venutian ast command shows the grammar the parser found: every statement a node, every name and literal a leaf.
    • Program
      • statements
        • FunctionDecl name add
          • params
            • Param name a
            • Param name b
          • body
            • GiveStatement
              • value
                • BinaryOp op +
                  • left
                    • Name identifier a
                  • right
                    • Name identifier b
        • AssignStatement
          • target
            • Name identifier t
          • value
            • SpawnExpr
              • call
                • Call
                  • callee
                    • Name identifier add
                  • args
                    • Node 0 false
                      • 1
                        • IntegerLiteral value 2
                    • Node 0 false
                      • 1
                        • IntegerLiteral value 3
        • PrintStatement
          • args
            • Call
              • callee
                • Name identifier kind
              • args
                • Node 0 false
                  • 1
                    • Name identifier t
        • PrintStatement
          • args
            • AwaitExpr
              • task
                • Name identifier t
        • FunctionDecl name slow_double
          • params
            • Param name n
          • body
            • ExprStatement
              • expr
                • Call
                  • callee
                    • Name identifier sleep
                  • args
                    • Node 0 false
                      • 1
                        • NumberLiteral value 0.05
            • GiveStatement
              • value
                • BinaryOp op *
                  • left
                    • Name identifier n
                  • right
                    • IntegerLiteral value 2
        • AssignStatement
          • target
            • Name identifier t1
          • value
            • SpawnExpr
              • call
                • Call
                  • callee
                    • Name identifier slow_double
                  • args
                    • Node 0 false
                      • 1
                        • IntegerLiteral value 1
        • AssignStatement
          • target
            • Name identifier t2
          • value
            • SpawnExpr
              • call
                • Call
                  • callee
                    • Name identifier slow_double
                  • args
                    • Node 0 false
                      • 1
                        • IntegerLiteral value 2
        • AssignStatement
          • target
            • Name identifier t3
          • value
            • SpawnExpr
              • call
                • Call
                  • callee
                    • Name identifier slow_double
                  • args
                    • Node 0 false
                      • 1
                        • IntegerLiteral value 3
        • PrintStatement
          • args
            • AwaitExpr
              • task
                • Name identifier t1
        • PrintStatement
          • args
            • AwaitExpr
              • task
                • Name identifier t2
        • PrintStatement
          • args
            • AwaitExpr
              • task
                • Name identifier t3
        • FunctionDecl name risky
          • body
            • GiveStatement
              • value
                • BinaryOp op /
                  • left
                    • IntegerLiteral value 1
                  • right
                    • IntegerLiteral value 0
        • AssignStatement
          • target
            • Name identifier failing_task
          • value
            • SpawnExpr
              • call
                • Call
                  • callee
                    • Name identifier risky
        • AttemptStatement
          • body
            • ExprStatement
              • expr
                • AwaitExpr
                  • task
                    • Name identifier failing_task
          • rescues
            • RescueClause var_name e
              • body
                • PrintStatement
                  • args
                    • TextLiteral value "rescued:"
                    • Name identifier e
        • ShareStatement name counter
          • value
            • IntegerLiteral value 0
        • FunctionDecl name increment_many effects "Concurrency"
          • params
            • Param name count
          • body
            • AssignStatement
              • target
                • Name identifier i
              • value
                • IntegerLiteral value 0
            • RepeatStatement
              • form
                • RepeatWhile
                  • condition
                    • BinaryOp op <
                      • left
                        • Name identifier i
                      • right
                        • Name identifier count
              • body
                • ProtectStatement name counter
                  • body
                    • AssignStatement
                      • target
                        • Name identifier counter
                      • value
                        • BinaryOp op +
                          • left
                            • Name identifier counter
                          • right
                            • IntegerLiteral value 1
                • AssignStatement
                  • target
                    • Name identifier i
                  • value
                    • BinaryOp op +
                      • left
                        • Name identifier i
                      • right
                        • IntegerLiteral value 1
        • AssignStatement
          • target
            • Name identifier tasks
          • value
            • ListLiteral
        • RepeatStatement
          • form
            • RepeatTimes
              • count
                • IntegerLiteral value 8
          • body
            • AssignStatement
              • target
                • Name identifier tasks
              • value
                • Call
                  • callee
                    • Name identifier appended
                  • args
                    • Node 0 false
                      • 1
                        • Name identifier tasks
                    • Node 0 false
                      • 1
                        • SpawnExpr
                          • call
                            • Call
                              • callee
                                • Name identifier increment_many
                              • args
                                • Node 0 false
                                  • 1
                                    • IntegerLiteral value 500
        • RepeatStatement
          • form
            • RepeatFor loop_var "t"
              • iterable
                • Name identifier tasks
          • body
            • ExprStatement
              • expr
                • AwaitExpr
                  • task
                    • Name identifier t
        • PrintStatement
          • args
            • Name identifier counter
  4. Bytecode

    The venutian disasm command lists the instructions the virtual machine runs, each operand resolved to the constant it names.
    main
    OffsetInstructionOperandConstant
    0LOAD_NAME13"add"
    1BUILD_LIST0
    2LOAD_CONST52
    3LIST_APPEND
    4LOAD_CONST143
    5LIST_APPEND
    6CALL0 15"new_map"
    7SPAWN
    8STORE_NAME16"t"
    9LOAD_NAME16"t"
    10CALL1 17"kind"
    11PRINT1
    12LOAD_NAME16"t"
    13AWAIT
    14PRINT1
    15LOAD_NAME18"slow_double"
    16BUILD_LIST0
    17LOAD_CONST61
    18LIST_APPEND
    19CALL0 15"new_map"
    20SPAWN
    21STORE_NAME19"t1"
    22LOAD_NAME18"slow_double"
    23BUILD_LIST0
    24LOAD_CONST52
    25LIST_APPEND
    26CALL0 15"new_map"
    27SPAWN
    28STORE_NAME20"t2"
    29LOAD_NAME18"slow_double"
    30BUILD_LIST0
    31LOAD_CONST143
    32LIST_APPEND
    33CALL0 15"new_map"
    34SPAWN
    35STORE_NAME21"t3"
    36LOAD_NAME19"t1"
    37AWAIT
    38PRINT1
    39LOAD_NAME20"t2"
    40AWAIT
    41PRINT1
    42LOAD_NAME21"t3"
    43AWAIT
    44PRINT1
    45LOAD_NAME22"risky"
    46BUILD_LIST0
    47CALL0 15"new_map"
    48SPAWN
    49STORE_NAME23"failing_task"
    50ENTER_ATTEMPT24
    51LOAD_NAME23"failing_task"
    52AWAIT
    53POP
    54EXIT_ATTEMPT
    55JUMP60
    56LOAD_CONST25"rescued:"
    57LOAD_NAME26"e"
    58PRINT2
    59JUMP60
    60LOAD_CONST70
    61MAKE_SHARED
    62STORE_NAME10"counter"
    63BUILD_LIST0
    64STORE_NAME27"tasks"
    65LOAD_CONST308
    66STORE_NAME28"$rt_len_3"
    67LOAD_CONST70
    68STORE_NAME29"$rt_idx_3"
    69LOAD_NAME29"$rt_idx_3"
    70LOAD_NAME28"$rt_len_3"
    71LT
    72JUMP_IF_FALSE87
    73LOAD_NAME27"tasks"
    74LOAD_NAME31"increment_many"
    75BUILD_LIST0
    76LOAD_CONST32500
    77LIST_APPEND
    78CALL0 15"new_map"
    79SPAWN
    80CALL2 33"appended"
    81STORE_NAME27"tasks"
    82LOAD_NAME29"$rt_idx_3"
    83LOAD_CONST61
    84ADD
    85STORE_NAME29"$rt_idx_3"
    86JUMP69
    87LOAD_NAME27"tasks"
    88STORE_NAME34"$rf_src_4"
    89LOAD_NAME34"$rf_src_4"
    90CALL1 36"$is_generator"
    91JUMP_IF_FALSE102
    92LOAD_NAME34"$rf_src_4"
    93CALL1 37"$has_next"
    94JUMP_IF_FALSE121
    95LOAD_NAME34"$rf_src_4"
    96CALL1 38"$next_value"
    97STORE_NAME16"t"
    98LOAD_NAME16"t"
    99AWAIT
    100POP
    101JUMP92
    102LOAD_CONST70
    103STORE_NAME35"$rf_idx_4"
    104LOAD_NAME35"$rf_idx_4"
    105LOAD_NAME34"$rf_src_4"
    106LEN
    107LT
    108JUMP_IF_FALSE121
    109LOAD_NAME34"$rf_src_4"
    110LOAD_NAME35"$rf_idx_4"
    111INDEX
    112STORE_NAME16"t"
    113LOAD_NAME16"t"
    114AWAIT
    115POP
    116LOAD_NAME35"$rf_idx_4"
    117LOAD_CONST61
    118ADD
    119STORE_NAME35"$rf_idx_4"
    120JUMP104
    121LOAD_NAME10"counter"
    122PRINT1
    123HALT
    function add(a, b)
    OffsetInstructionOperandConstant
    0LOAD_NAME0"a"
    1LOAD_NAME1"b"
    2ADD
    3RETURN
    4RETURN_NOTHING
    function slow_double(n)
    OffsetInstructionOperandConstant
    0LOAD_CONST20.05
    1CALL1 3"sleep"
    2POP
    3LOAD_NAME4"n"
    4LOAD_CONST52
    5MUL
    6RETURN
    7RETURN_NOTHING
    function risky()
    OffsetInstructionOperandConstant
    0LOAD_CONST61
    1LOAD_CONST70
    2DIV
    3RETURN
    4RETURN_NOTHING
    function increment_many(count)
    OffsetInstructionOperandConstant
    0LOAD_CONST70
    1STORE_NAME8"i"
    2LOAD_NAME8"i"
    3LOAD_NAME9"count"
    4LT
    5JUMP_IF_FALSE23
    6PROTECT_ENTER10"counter"
    7ENTER_ATTEMPT11
    8LOAD_NAME10"counter"
    9LOAD_CONST61
    10ADD
    11STORE_NAME10"counter"
    12EXIT_ATTEMPT
    13PROTECT_EXIT10"counter"
    14JUMP18
    15PROTECT_EXIT10"counter"
    16LOAD_NAME12"$protect_exc_2"
    17RAISE
    18LOAD_NAME8"i"
    19LOAD_CONST61
    20ADD
    21STORE_NAME8"i"
    22JUMP2
    23RETURN_NOTHING
  5. Output

    The venutian run command compiles the program and runs it on the native virtual machine, and this is what it printed.
    Task
    5
    2
    4
    6
    rescued: Division by zero.
    4000

    exit 0

The playground

Nine real programs, each with its recorded output and timing. Run compiles a program with Venutian's self hosted compiler and executes it on the native virtual machine, compiled to WebAssembly and running in your browser.

  1. hello.ven
    print "Hello from Venutian"
    Output of hello.ven
    Hello from Venutian
  2. guards.ven
    make grade(score)
        choose score
            is n: Integer where n >= 90
                give "A"
            is n: Integer where n >= 80
                give "B"
            is n: Integer where n >= 70
                give "C"
            is : Integer
                give "F"
            otherwise
                give "not a number"
    
    print grade(95)
    print grade(82)
    print grade(71)
    print grade(50)
    print grade("ninety")
    Output of guards.ven
    A
    B
    C
    F
    not a number
  3. concurrency.ven
    :: 'spawn call_expr' starts a real OS thread running the call right now
    :: and returns a Task immediately, without waiting. 'await task' blocks
    :: until it finishes, returning its result, or re-raising its fault.
    
    make add(a, b)
        give a + b
    
    t = spawn add(2, 3)
    print kind(t)
    print await t
    
    :: several tasks make genuine concurrent progress
    make slow_double(n)
        sleep(0.05)
        give n * 2
    
    t1 = spawn slow_double(1)
    t2 = spawn slow_double(2)
    t3 = spawn slow_double(3)
    print await t1
    print await t2
    print await t3
    
    :: a fault inside a spawned task surfaces at 'await', not silently
    make risky()
        give 1 / 0
    
    failing_task = spawn risky()
    attempt
        await failing_task
    rescue e
        print "rescued:", e
    
    :: 'share'/'protect': real mutual exclusion across real threads
    share counter = 0
    
    make increment_many(count)
        i = 0
        repeat while i < count
            protect counter
                counter = counter + 1
            i = i + 1
    
    tasks = []
    repeat 8 times
        tasks = appended(tasks, spawn increment_many(500))
    
    repeat for t in tasks
        await t
    
    :: exactly 4000 (8 * 500) every time. 'protect' prevents lost updates
    print counter
    Output of concurrency.ven
    Task
    5
    2
    4
    6
    rescued: Division by zero.
    4000

Run it on your own machine.

macOS, Apple silicon

curl -fsSL https://venutian.org/install.sh | sh

Linux

x86_64 and arm64. Ubuntu, Debian, Fedora, Alpine and friends.

curl -fsSL https://venutian.org/install.sh | sh

Windows

irm https://venutian.org/install.ps1 | iex
powershell -c "irm https://venutian.org/install.ps1 | iex"

Self hosting in five stages

Venutian's own compiler pipeline is written in Venutian, one stage at a time, each stage checked against the reference implementation before the next one starts.

  1. Tokenizer

    A real tokenizer for a small expression language, written entirely in Venutian (examples/self_hosting_lexer.ven).

  2. Lexer port

    A line for line port of the production lexer, checked token by token against the reference lexer over the whole example corpus.

  3. Parser and checker

    Ports of the production parser and semantic analyzer, checked by AST equality and accept and reject tests.

  4. Code generator

    A port of the production code generator (1,133 lines of Venutian) plus the VBC serializer, so the whole pipeline runs in Venutian and emits a loadable .vbc file.

  5. Native VM

    A from scratch native virtual machine with no third party libraries. From here, new programs compile and run with nothing but Venutian in the loop.

Native ahead of time compilation

venutian build --native compiles ahead of time with the same compiler and binary that produced every number on the performance page. Two decisions do the work: the recursive body of a hot function is inlined once, and a frameless base case skips building a stack frame for the branch that just returns.

On fib(30) the result runs 43.6 million instructions against clang's 45.5 million on the same round: 1.000x the cycles of clang -O2 and 0.985x the wall time, from a compiler written in Venutian.

Terminal, macOS
$ venutian build --native hello.ven
n3: wrote hello bytes=33440 words=2253 functions=1
Then run it
$ ./hello
Hello from Venutian