-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathtsp-generate-math.tcl
150 lines (126 loc) · 5.34 KB
/
tsp-generate-math.tcl
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# compiled math commands:
# expr, incr
#########################################################
# generate code for "expr" command (assumed to be first parse word)
# only braced arguments are generated, anything else generates an error
# return list of: type rhsVarName code
#
proc ::tsp::gen_command_expr {compUnitDict tree} {
upvar $compUnitDict compUnit
if {[llength $tree] != 2} {
::tsp::addError compUnit "wrong # args: should be \"expr arg\""
return [list void "" ""]
}
# just get raw text from body
set rawtext [::tsp::parse_getstring compUnit [lindex $tree 1]]
if { [string range $rawtext 0 0] ne "\{"} {
::tsp::addError compUnit "expr argument not a braced expression"
return [list void "" ""]
}
set exprtext [lindex $rawtext 0]
set rc [catch {set exprTypeCode [::tsp::compileExpr compUnit $exprtext]} result]
if {$rc != 0} {
::tsp::addError compUnit "couldn't parse expr: \"$exprtext\", $result"
return [list void "" ""]
}
lassign $exprTypeCode type exprCode
set tmpVar [::tsp::get_tmpvar compUnit $type]
set code [::tsp::lang_expr compUnit "$tmpVar = $exprCode;"]
return [list $type $tmpVar $code]
}
#########################################################
# generate code for "incr" command (assumed to be first parse word)
# return list of: type rhsVarName code
# FIXME: support array targets?
#
proc ::tsp::gen_command_incr {compUnitDict tree} {
upvar $compUnitDict compUnit
if {[llength $tree] < 2 || [llength $tree] > 3} {
::tsp::addError compUnit "wrong # args: should be \"incr varName ?increment?\""
return [list void "" ""]
}
set varname [::tsp::nodeText compUnit [lindex $tree 1]]
if {$varname eq ""} {
::tsp::addError compUnit "incr varName argument requires a scalar varName"
return [list void "" ""]
}
set vartype [::tsp::getVarType compUnit $varname]
if {$vartype eq "undefined"} {
if {[::tsp::isProcArg compUnit $varname]} {
::tsp::addError compUnit "proc argument variable \"$varname\" not previously defined"
return [list void "" ""]
} elseif {[::tsp::isValidIdent $varname]} {
::tsp::addWarning compUnit "variable \"${varname}\" implicitly defined as type: \"int\" (incr)"
::tsp::setVarType compUnit $varname int
set vartype int
} else {
::tsp::addError compUnit "invalid identifier: \"$varname\""
return [list void "" ""]
}
}
if {$vartype ne "int" && $vartype ne "var"} {
::tsp::addError compUnit "incr argument varName must be type \"int\" or \"var\""
return [list void "" ""]
}
set incrAmount 1
set incrvar ""
set incrtype ""
if {[llength $tree] == 3} {
set incrComponent [lindex [::tsp::parse_word compUnit [lindex $tree 2]] 0]
lassign $incrComponent type incrvar incrtext
if {$type eq "text"} {
# make sure text is an integer
if {[::tsp::literalExprTypes $incrtext] ne "int"} {
::tsp::addError compUnit "incr amount argument is not an integer: \"$incrtext\""
return [list void "" ""]
}
set incrAmount $incrtext
set incrvar ""
} elseif {$type eq "scalar"} {
set incrtype [::tsp::getVarType compUnit $incrvar]
if {$incrtype ne "int" && $incrtype ne "var"} {
::tsp::addError compUnit "incr amount argument varName must be type \"int\" or \"var\""
return [list void "" ""]
}
} else {
::tsp::addError compUnit "incr amount argument must be a integer or a scalar variable"
return [list void "" ""]
}
}
# check if either varname or incrvar are temp variables, otherwise prefix user vars with "__"
set pre [::tsp::var_prefix $varname]
set varname $pre$varname
if {$incrvar ne ""} {
set pre [::tsp::var_prefix $incrvar]
set incrvar $pre$incrvar
}
# if target is a var, use a temp var for increment and assignment rhsVar
if {$vartype eq "var"} {
set rhsVar [::tsp::get_tmpvar compUnit int]
set errMsg [::tsp::gen_runtime_error compUnit [::tsp::lang_quote_string "unable to convert var to int, \"$varname\", value: "]]
append code [::tsp::lang_convert_int_var $rhsVar $varname $errMsg]
} else {
set rhsVar $varname
}
# if incr var is a var, use a temp var for increment
if {$incrvar ne ""} {
if {$incrtype eq "var"} {
set incrsource [::tsp::get_tmpvar compUnit int]
set errMsg [::tsp::gen_runtime_error compUnit [::tsp::lang_quote_string "unable to convert var to int, \"$incrvar\", value: "]]
append code [::tsp::lang_convert_int_var $incrsource $incrvar $errMsg]
} else {
set incrsource $incrvar
}
} else {
set incrsource $incrAmount
}
append code "$rhsVar = $rhsVar + ($incrsource);\n"
# if target var is a var, update the var with the incr amount
if {$vartype eq "var"} {
append code [::tsp::lang_assign_var_int $varname $rhsVar]
}
# native var has been assigned, so mark it as dirty
# puts "gen_command_incr- ::tsp::setDirty compUnit $varname"
::tsp::setDirty compUnit $varname
return [list int $rhsVar $code]
}