summaryrefslogtreecommitdiff
path: root/ast/ast.odin
blob: 8007e5433a1a3115a38bf4e0e143ce1d09ba98f6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package ast

import "../token"
import "core:bytes"

THIRTY_TWO_KILOBYTES := 262144

Node :: union {
	Program,
	Statement,
	Expression,
}

Program :: struct {
	statements: []Statement,
}

Statement :: union {
	Let_Statement,
    Return_Statement,
}

Let_Statement :: struct {
	token: token.Token,
	name:  Identifier,
	value: Expression,
}

Return_Statement :: struct {
    token: token.Token,
    return_value: Expression,
}

Expression_Statement :: struct {
    token: token.Token,
    expression: Expression,
}

Expression :: union {
	Identifier,
}

Identifier :: struct {
	token: token.Token,
	value: string,
}


token_literal :: proc(node: Node) -> (literal: string) {
	switch n in node {
	case Program:
		if len(n.statements) > 0 {
			stmt: Node = n.statements[0]
			literal = token_literal(stmt)
		}
	case Statement:
		switch s in n {
		case Let_Statement:
			literal = token.literal(s.token)
        case Return_Statement:
            literal = token.literal(s.token)
        case Expression_Statement:
            literal = token.literal(s.token)
		}
	case Expression:
		switch e in n {
		case Identifier:
			literal = token.literal(e.token)
		}
	}
	return literal
}

node_to_string :: proc(node: Node) -> string {
    out: bytes.Buffer
    bytes.buffer_init_allocator(&out, 4, THIRTY_TWO_KILOBYTES, context.temp_allocator)

	switch n in node {
	case Program:
        for stmt in n {
            bytes.buffer_write_string(&out, node_to_string(n))
        }
	case Statement:
		switch s in n {
		case Let_Statement:
			bytes.buffer_write_string(&out, token.literal(s.token) + " ")
			bytes.buffer_write_string(&out, node_to_string(s.name))
			bytes.buffer_write_string(&out, " = ")
            if s.value != nil {
                bytes.buffer_write_string(&out, node_to_string(s.value))
            }
            bytes.buffer_write_string(&out, ";")
        case Return_Statement:
			bytes.buffer_write_string(&out, token.literal(s.token) + " ")
            if s.return_value != nil {
                bytes.buffer_write_string(&out, node_to_string(s.return_value))
            }
        case Expression_Statement:
            if s.expression != nil {
                bytes.buffer_write_string(&out, node_to_string(s.expression))
            }
		}
	case Expression:
		switch e in n {
		case Identifier:
			literal = token.literal(e.token)
		}
	}

	return bytes.buffer_to_string(&out)
}