3
« on: January 06, 2020, 05:43:36 PM »
С помощью препроцессора вполне возможно сделать хоть и немного кривые, но функции.
С локальными переменными и возвращаемыми значениями.
s = `
sub(ar, $i, $j)
$ret = $arr[$i+10*$j+11]
end_sub
ar(1, 2)
$v1 = ar(1, ar(2, sin(3))))
$v2 = sin(ar(2, sin(3)))
$v3 = ar(ar(1, 2), ar(3, 4))
`;
a = s.split('\n');
b = [];
localvars = new Map();
subname = ''
subnames = new Set();
// todo: make both 'SUB' and 'sub' support
a = a.map(s=>{
if (s.startsWith('sub(')) {
subname = s.match(/\(\s*(\w+)/)[1];
subnames.add(subname);
localvars = new Map();
localvars.set('$ret', '$_' + subname + '_ret');
return s.replace(/\$\w+/g, s=>{
localvars.set(s, '$_' + subname + '_' + localvars.size);
return localvars.get(s);
}
);
}
if (s.startsWith('end_sub')) {
localvars = new Map();
return s;
}
return s.replace(/\$\w+/g, s=>{
return localvars.get(s) || s;
}
);
}
)
a2 = [];
tempn = 0;
for (let s of a) {
if (s.match(/^\s*(sub|for|while|do|if)\s*\(/)) {
a2.push(s);
continue;
}
let ws = s.match(/^\s*/)[0];
// todo: make "(" string support
let temps = []
for (let i = 0; i < 10; i++) {
s = s.replace(/(\w+)\([^()]*\)/, (s, fname) => {
let tempname = '$_temp_' + (++tempn)
let o = {type: 'call', s, fname, n: tempn, tempname};
o.id = temps.push(o);
return tempname;
})
}
let inlines = new Map();
for (let o of temps) {
for (let i = 0; i < 10; i++) {
o.s = o.s.replace(/\$_temp_\w+/, s => inlines.get(s) || s)
}
if (subnames.has(o.fname)) {
a2.push(ws + o.s);
a2.push(ws + o.tempname + ' = $_' + o.fname + '_ret');
} else {
inlines.set(o.tempname, o.s)
}
}
for (let i = 0; i < 10; i++) {
s = s.replace(/\$_temp_\w+/, s => inlines.get(s) || s)
}
a2.push(s);
}
s = a2.join('\n')
console.log('%o', s);
Из
sub(ar, $i, $j)
$ret = $arr[$i+10*$j+11]
end_sub
ar(1, 2)
$v1 = ar(1, ar(2, sin(3))))
$v2 = sin(ar(2, sin(3)))
$v3 = ar(ar(1, 2), ar(3, 4))
генерирует
sub(ar, $_ar_1, $_ar_2)
$_ar_ret = $arr[$_ar_1+10*$_ar_2+11]
end_sub
ar(1, 2)
$_temp_1 = $_ar_ret
$_temp_1
ar(2, sin(3))
$_temp_3 = $_ar_ret
ar(1, $_temp_3)
$_temp_4 = $_ar_ret
$v1 = $_temp_4)
ar(2, sin(3))
$_temp_6 = $_ar_ret
$v2 = sin($_temp_6)
ar(1, 2)
$_temp_8 = $_ar_ret
ar(3, 4)
$_temp_9 = $_ar_ret
ar($_temp_8, $_temp_9)
$_temp_10 = $_ar_ret
$v3 = $_temp_10
Если кто может перевести в dll (сам на подходящих языках плохо пишу), пожалуйста скомпилируйте.