Changeset 19
Author: Leszek Godlewski
(2010/01/19 04:32) Over 2 years ago
islip: * compiler, interpreter, variable: added ability to print to stderr (INVISIBLE keyword) * bytecode, compiler, interpreter: added incrementation operation * variable: fixed a bug that would cause all float to string casts to result with a "0" * compiler: fixed a bug with nested loop breaks not recognized as proper language keywords * compiler: removed identifiers from constants * compiler: fixed a bug that would cause erratic conditional jumps in some else-if statements * compiler: fixed a crash caused by an unitialized ipcont object * compiler: fixed constant loading logic * compiler: added the KTHX instruction to terminate program prematurely (own extension, not in spec)
function eval_statement(gtfo : pislip_cmp_ipcont) : boolean;// list element for ipcontpislip_cmp_ip = ^islip_cmp_ip;islip_cmp_ip = recordi : pislip_cmp_inst;next : pislip_cmp_ip;end;// helper class to manage a linked list of instruction pointers to simplify// jumping out of success blocks to after the non-linear code blockislip_cmp_ipcont = classpublicconstructor create;// fills the arguments of all elements with ofsprocedure fill(ofs : int);// adds a pointer to an instruction to listprocedure add(i : pislip_cmp_inst);privatem_head : pislip_cmp_ip;m_tail : pislip_cmp_ip;end;if not (token[1] in ['0'..'9']) or (token[1] = '-') then beginif not ((token[1] in ['0'..'9']) or (token[1] = '-')) then begin{$IFDEF DEBUG}{$IFDEF DEBUG}{$ENDIF}{$ENDIF}m_code.append(OP_PUSH, m_vars.append(pv, token));m_code.append(OP_PUSH, m_vars.append(pv, ''));{$IFDEF DEBUG}{$IFDEF DEBUG}{$ENDIF}{$ENDIF}m_code.append(OP_PUSH, m_vars.append(pv, token));m_code.append(OP_PUSH, m_vars.append(pv, ''));m_code.append(OP_PUSH, m_vars.append(pv, token));m_code.append(OP_PUSH, m_vars.append(pv, ''));m_code.append(OP_PUSH, m_vars.append(v, token));m_code.append(OP_PUSH, m_vars.append(v, ''));function islip_compiler.eval_statement(gtfo : pislip_cmp_ipcont) : boolean;writeln ('ERROR: "RLY?" expected, but got "', token, '" at ',writeln('ERROR: "RLY?" expected, but got "', token, '" at ',writeln ('ERROR: "YA" expected, but got "', token, '" at ',writeln('ERROR: "YA" expected, but got "', token, '" at ',writeln ('ERROR: "RLY" expected, but got "', token, '" at ',writeln('ERROR: "RLY" expected, but got "', token, '" at ',if token = 'OIC' then beginif flowstate <> FS_ELSE theni^.arg := m_code.m_count + 1;i^.arg := m_code.m_count + 2;if not eval_statement(gtfo) thenm_code.append(OP_PUSH, m_vars.append(pv, token));m_code.append(OP_PUSH, m_vars.append(pv, ''));writeln ('ERROR: Literal expected, but got "', token,writeln ('ERROR: Literal expected, but got "', token,if not eval_statement(nil) thenwriteln('ERROR: Unexpected end of file');writeln('ERROR: Unexpected end of file');while m_parser.get_token(token, toktype) do beginwhile true do beginm_parser.unget_token;end else if token = 'GTFO' then begin// add a jump out of the loopipcont.add(m_code.append(OP_JMP, ARG_NULL));continue;if not eval_statement(@ipcont) then// save off the instruction count// fetch next tokensc := m_code.m_count;if not m_parser.get_token(token, toktype) then begin// evaluate the expressionwriteln('ERROR: Unexpected end of file');if not eval_expr() then beginm_parser.get_pos(sr, sc);writeln('ERROR: Unable to evaluate expression at ','line ', sr, ', column ', sc);// if the variable already exists, it's been initialized// check if this is a literal// somewhere else already, so just pop the top of the stackif toktype = TT_STRING then begin// into itnew(pv);if v <> nil thenpv^ := islip_var.create(token);// FIXME: put index into islip_cmp_varm_vars.append(pv, id);m_code.append(OP_POP, m_vars.get_var_index(v^.id))// if the variable already exists, it's been initializedelse begin// somewhere else already, so just pop the nev value into it;// if the expression generates only 1 instruction, it// otherwise it's a constant and doesn't even need to be put onto// must be a constant, so let's reduce instructions// the stackif m_code.m_count - sc = 1 then beginif v <> nil then begin// the last one in the list will be the one we needm_code.append(OP_PUSH, m_vars.m_index);// FIXME: put index into islip_cmp_varm_code.append(OP_POP, m_vars.get_var_index(v^.id));end;end else if literal(token) then begin// if the variable already exists, it's been initialized// somewhere else already, so just pop the top of the stack// into itif v = nil then begin// remove the last OP_PUSH and set variable identifier// else we need to calculate the result, so allocateend else// a new data slot// FIXME: put index into islip_cmp_varend else beginm_code.append(OP_POP, m_vars.get_var_index(v^.id));end else beginm_parser.unget_token;// evaluate the expressionif not eval_expr() then beginm_parser.get_pos(sr, sc);writeln('ERROR: Unable to evaluate expression at ','line ', sr, ', column ', sc);exit;end;// if the variable already exists, it's been initialized// somewhere else already, so just pop the top of the stack// into itif v <> nil then// FIXME: put index into islip_cmp_varm_code.append(OP_POP, m_vars.get_var_index(v^.id))else beginend else if token = 'VISIBLE' then beginend else if (token = 'VISIBLE') or (token = 'INVISIBLE') then beginm_code.append(OP_PRINT, ARG_NULL);// differentiate between stdio and stderrif token[1] = 'I' thenm_code.append(OP_PRINT, 1)elsem_code.append(OP_PRINT, ARG_NULL);writeln('ERROR: Unexpected end of file');writeln('ERROR: Unexpected end of file');end else begin// HACK HACK HACK!!! a not-so-ellegant way of catching loop breaksend else if (gtfo <> nil) and (token = 'GTFO') thengtfo^.add(m_code.append(OP_JMP, ARG_NULL))// exit from program// NOTE: a custom extension, not included in the specelse if token = 'KTHX' thenm_code.append(OP_STOP, ARG_NULL)else beginif not eval_statement(nil) then begin//writeln('ERROR: Unable to parse script');//writeln('ERROR: Unable to parse script');v.echo;if m_code^[i].arg = 1 then beginwriteln;v.echo(true);writeln(stderr);end else beginv.echo(false);writeln;end;writeln('ERROR: Invalid instruction 0x',writeln('ERROR: Invalid instruction 0x',write(' 0x', IntToHex(i, 8), ' = ');write(' 0x', IntToHex(i, 8), ' = ');write('"');write('"');g_data[i].echo(false);write('"');write('"');while m_reader.get_char(c) do beginend;// prints the variable to stdout or stderrprocedure echo(to_stderr : boolean);// frees the value pointed to by m_valptrprocedure reset_value;procedure islip_var.echo(to_stderr : boolean);write(pi^);if to_stderr thenwrite(stderr, pi^)elsewrite(pi^);write(pf^:0:2);if to_stderr thenwrite(stderr, pf^:0:2)elsewrite(pf^:0:2);write(ps^);if to_stderr thenwrite(stderr, ps^)elsewrite(ps^);if pb^ thenif to_stderr then beginwrite('WIN')if pb^ thenelsewrite(stderr, 'WIN')write('FAIL');elsewrite(stderr, 'FAIL');end else beginif pb^ thenwrite('WIN')elsewrite('FAIL');end;ps^ := FloatToStr(pi^);ps^ := FloatToStr(pf^);