Changeset 6

User picture

Author: Leszek Godlewski

(2009/12/08 18:22) Over 2 years ago

islip:
* added Turbo Delphi project wrapper
* changed data indexing convention to start at 1, allowing for ARG_NULL 
to be 0
* fixed a bug with zero-length Turbo Delphi strings

Affected files

Updated islip/bytecode.pas Download diff

56
16
    // STOP: stop the execution of the program
16
    // STOP: stop the execution of the program
17
    // args: n/a
17
    // args: n/a
18
    // result: n/a
18
    // result: n/a
19
    BI_STOP         =   $00;
19
    OP_STOP         =   $00;
20
20
21
    // PUSH: push variable onto the stack
21
    // PUSH: push variable onto the stack
22
    // args: index of the variable to read from and put on the stack
22
    // args: index of the variable to read from and put on the stack
23
    // result: the variable is on the top of the stack
23
    // result: the variable is on the top of the stack
24
    BI_PUSH         =   $01;
24
    OP_PUSH         =   $01;
25
25
26
    // POP: pop variable off the stack
26
    // POP: pop variable off the stack
27
    // args: index of the variable to write the value off the stack to
27
    // args: index of the variable to write the value off the stack to
28
    // result: the top-most variable is removed from the stack
28
    // result: the top-most variable is removed from the stack
29
    BI_POP          =   $02;
29
    OP_POP          =   $02;
30
30
31
    // ADD: addition of the two top-most variables on the stack
31
    // ADD: addition of the two top-most variables on the stack
32
    // args: n/a
32
    // args: n/a
33
    // result: pops the two top-most variables and pushes the operation result
33
    // result: pops the two top-most variables and pushes the operation result
34
    BI_ADD          =   $03;
34
    OP_ADD          =   $03;
35
35
36
    // ADD: subtraction of the two top-most variables on the stack
36
    // ADD: subtraction of the two top-most variables on the stack
37
    // args: n/a
37
    // args: n/a
38
    // result: pops the two top-most variables and pushes the operation result
38
    // result: pops the two top-most variables and pushes the operation result
39
    BI_SUB          =   $04;
39
    OP_SUB          =   $04;
40
40
41
    // MUL: multiplication of the two top-most variables on the stack
41
    // MUL: multiplication of the two top-most variables on the stack
42
    // args: n/a
42
    // args: n/a
43
    // result: pops the two top-most variables and pushes the operation result
43
    // result: pops the two top-most variables and pushes the operation result
44
    BI_MUL          =   $05;
44
    OP_MUL          =   $05;
45
45
46
    // DIV: division of the two top-most variables on the stack
46
    // DIV: division of the two top-most variables on the stack
47
    // args: n/a
47
    // args: n/a
48
    // result: pops the two top-most variables and pushes the operation result
48
    // result: pops the two top-most variables and pushes the operation result
49
    BI_DIV          =   $06;
49
    OP_DIV          =   $06;
50
50
51
    // JMP: unconditional jump
51
    // JMP: unconditional jump
52
    // args: instruction offset to apply
52
    // args: instruction offset to apply
53
    // result: corresponding pointer arithmetic on the interpreter's instruction pointer
53
    // result: corresponding pointer arithmetic on the interpreter's instruction pointer
54
    BI_JMP          =   $07;
54
    OP_JMP          =   $07;
55
55
56
    // CNDJMP: conditional jump (if top of the stack < 0)
56
    // CNDJMP: conditional jump (if top of the stack < 0)
57
    // args: instruction offset to apply if condition is true
57
    // args: instruction offset to apply if condition is true
58
    // result: corresponding pointer arithmetic on the interpreter's instruction pointer
58
    // result: corresponding pointer arithmetic on the interpreter's instruction pointer
59
    BI_CNDJMP       =   $08;
59
    OP_CNDJMP       =   $08;
60
60
61
    // TRAP: call an interpreter trap
61
    // TRAP: call an interpreter trap
62
    // args: ID of the routine to call
62
    // args: ID of the routine to call
63
    // result: n/a
63
    // result: n/a
64
    BI_TRAP         =   $09;
64
    OP_TRAP         =   $09;
65
65
66
    // CALL: call a function (defined in LOLCODE); assumes that parameters are on the stack (stdcall convention)
66
    // CALL: call a function (defined in LOLCODE); assumes that parameters are on the stack (stdcall convention)
67
    // args: function index
67
    // args: function index
68
    // result: function's return value on top of the stack
68
    // result: function's return value on top of the stack
69
    BI_CALL         =   $0A;
69
    OP_CALL         =   $0A;
70
70
71
    // ====================================================
71
    // ====================================================
72
    // interpreter traps
72
    // interpreter traps
...
...
85
    // NULL argument
85
    // NULL argument
86
    // PUSH behaviour: push an empty variable onto the stack
86
    // PUSH behaviour: push an empty variable onto the stack
87
    // POP behaviour: just pop the stack without writing the value to a variable
87
    // POP behaviour: just pop the stack without writing the value to a variable
88
    ARG_NULL        =   $FFFFFFFF;
88
    ARG_NULL        =   $00000000;
89
89
90
type
90
type
91
    // single instruction with the argument
91
    // single instruction with the argument

Updated islip/compiler.pas Download diff

56
26
    // variable container
26
    // variable container
27
    islip_cmp_var_cont  = class
27
    islip_cmp_var_cont  = class
28
        public
28
        public
29
            m_head      : pislip_cmp_var;
30
            m_tail      : pislip_cmp_var;
31
            m_index     : size_t;
32
            
29
            constructor create;
33
            constructor create;
30
            destructor destroy; override;
34
            destructor destroy; override;
31
35
32
            // appends the new variable to the list and returns its index
36
            // appends the new variable to the list and returns its index
33
            function append(v : pislip_var) : size_t;
37
            function append(v : pislip_var) : size_t;
34
35
            m_head      : pislip_cmp_var;
36
            m_tail      : pislip_cmp_var;
37
            m_index     : size_t;
38
    end;
38
    end;
39
39
40
    // instruction linked list element
40
    // instruction linked list element
...
...
48
    // instruction container
48
    // instruction container
49
    islip_cmp_code_cont = class
49
    islip_cmp_code_cont = class
50
        public
50
        public
51
            m_head      : pislip_cmp_inst;
52
            m_tail      : pislip_cmp_inst;
53
            m_count     : size_t;
54
51
            constructor create;
55
            constructor create;
52
            destructor destroy; override;
56
            destructor destroy; override;
53
57
54
            // appends the new instruction to the list and returns its index
58
            // appends the new instruction to the list and returns its index
55
            procedure append(i : byte; arg : size_t);
59
            procedure append(i : byte; arg : size_t);
56
57
            m_head      : pislip_cmp_inst;
58
            m_tail      : pislip_cmp_inst;
59
            m_count     : size_t;
60
    end;
60
    end;
61
61
62
    islip_compiler          = class
62
    islip_compiler          = class
63
        public
63
        public
64
            constructor create(var input : file);
64
            constructor create(var input : cfile);
65
            destructor destroy; override;
65
            destructor destroy; override;
66
66
67
            // returns false on compilation failure
67
            // returns false on compilation failure
68
            function compile : boolean;
68
            function compile : boolean;
69
            procedure get_products(var c : islip_bytecode; var d : islip_data);
69
            procedure get_products(var c : islip_bytecode; var d : islip_data);
70
        private
70
        private
71
            function eval_expr(end_token : string) : boolean;
72
73
            m_parser    : islip_parser;
71
            m_parser    : islip_parser;
74
            m_vars      : islip_cmp_var_cont;
72
            m_vars      : islip_cmp_var_cont;
75
            m_code      : islip_cmp_code_cont;
73
            m_code      : islip_cmp_code_cont;
76
            m_done      : boolean;
74
            m_done      : boolean;
75
76
            function eval_expr(end_token : string) : boolean;
77
    end;
77
    end;
78
78
79
implementation
79
implementation
...
...
92
// compiler implementation
92
// compiler implementation
93
// ====================================================
93
// ====================================================
94
94
95
constructor islip_compiler.create(var input : file);
95
constructor islip_compiler.create(var input : cfile);
96
begin
96
begin
97
    m_parser := islip_parser.create(input);
97
    m_parser := islip_parser.create(input);
98
    m_vars := islip_cmp_var_cont.create;
98
    m_vars := islip_cmp_var_cont.create;
...
...
235
                        v^ := islip_var.create(token, token);
235
                        v^ := islip_var.create(token, token);
236
                        index := m_vars.append(v);
236
                        index := m_vars.append(v);
237
                        // generate the instructions
237
                        // generate the instructions
238
                        m_code.append(BI_PUSH, index);
238
                        m_code.append(OP_PUSH, index);
239
                        m_code.append(BI_TRAP, TRAP_PRINT);
239
                        m_code.append(OP_TRAP, TRAP_PRINT);
240
                        m_code.append(BI_POP, ARG_NULL);
240
                        m_code.append(OP_POP, ARG_NULL);
241
                    end;
241
                    end;
242
                    // add a line feed
242
                    // add a line feed
243
                    m_code.append(BI_TRAP, TRAP_LINEFEED);
243
                    m_code.append(OP_TRAP, TRAP_LINEFEED);
244
                    continue;
244
                    continue;
245
                // program end
245
                // program end
246
                end else if token = 'KTHXBYE' then begin
246
                end else if token = 'KTHXBYE' then begin
247
                    // add a STOP and end parsing
247
                    // add a STOP and end parsing
248
                    m_code.append(BI_STOP, 0);
248
                    m_code.append(OP_STOP, ARG_NULL);
249
                    token := '';
249
                    token := '';
250
                    break;
250
                    break;
251
                // skip newlines
251
                // skip newlines
...
...
261
    if length(token) > 0 then begin
261
    if length(token) > 0 then begin
262
        writeln('ERROR: Unable to parse script');
262
        writeln('ERROR: Unable to parse script');
263
        compile := false;
263
        compile := false;
264
        exit;
264
    end;
265
    end;
265
    m_done := true;
266
    m_done := true;
266
    compile := true;
267
    compile := true;
...
...
287
        d[i] := pv^.v^;
288
        d[i] := pv^.v^;
288
        pv := pv^.next;
289
        pv := pv^.next;
289
{$IFDEF DEBUG}
290
{$IFDEF DEBUG}
290
        write('DEBUG: variable #', i - 1, ' = ');
291
        write('DEBUG: variable #', i, ' = ');
291
        d[i].echo;
292
        d[i].echo;
292
        writeln;
293
        writeln;
293
{$ENDIF}
294
{$ENDIF}
...
...
335
var
336
var
336
    p   : pislip_cmp_var;
337
    p   : pislip_cmp_var;
337
begin
338
begin
339
    inc(m_index);
338
    append := m_index;
340
    append := m_index;
339
    inc(m_index);
340
    new(p);
341
    new(p);
341
    p^.v := v;
342
    p^.v := v;
342
    p^.next := nil;
343
    p^.next := nil;

Updated islip/interpreter.pas Download diff

56
58
begin
58
begin
59
    for i := 1 to length(m_code^) do begin
59
    for i := 1 to length(m_code^) do begin
60
        case m_code^[i].inst of
60
        case m_code^[i].inst of
61
            BI_STOP:
61
            OP_STOP:
62
                break;
62
                break;
63
            BI_PUSH:
63
            OP_PUSH:
64
                if m_code^[i].arg = ARG_NULL then
64
                if m_code^[i].arg = ARG_NULL then
65
                    m_stack.push(nil)
65
                    m_stack.push(nil)
66
                else
66
                else
67
                    m_stack.push(@m_data^[m_code^[i].arg + 1]);
67
                    m_stack.push(@m_data^[m_code^[i].arg]);
68
            BI_POP:
68
            OP_POP:
69
                if m_code^[i].arg = ARG_NULL then
69
                if m_code^[i].arg = ARG_NULL then
70
                    m_stack.pop(nil)
70
                    m_stack.pop(nil)
71
                else
71
                else
72
                    m_stack.pop(@m_data^[m_code^[i].arg + 1]);
72
                    m_stack.pop(@m_data^[m_code^[i].arg]);
73
            BI_TRAP:
73
            OP_TRAP:
74
                case m_code^[i].arg of
74
                case m_code^[i].arg of
75
                    TRAP_PRINT:
75
                    TRAP_PRINT:
76
                        begin
76
                        begin

Added islip/islip.bdsproj

Show contents

Added islip/islip.dpr

Show contents

Updated islip/islip.pas Download diff

56
29
var
29
var
30
    g_options       : islip_options;
30
    g_options       : islip_options;
31
    
31
    
32
    g_script        : file of byte;
32
    g_script        : cfile;
33
33
34
    g_compiler      : islip_compiler;
34
    g_compiler      : islip_compiler;
35
    g_interpreter   : islip_interpreter;
35
    g_interpreter   : islip_interpreter;
...
...
107
    g_interpreter.destroy;
107
    g_interpreter.destroy;
108
108
109
    // kthxbai!
109
    // kthxbai!
110
    readln;
110
end.
111
end.

Updated islip/parser.pas Download diff

56
13
uses typedefs;
13
uses typedefs;
14
14
15
type
15
type
16
    // helper type
16
    // helper types
17
    pstring = ^string;
17
    pstring = ^string;
18
18
19
    // retrieves characters from file, keeping track of the cursor position
19
    // retrieves characters from file, keeping track of the cursor position
20
    islip_reader = class
20
    islip_reader = class
21
        public
21
        public
22
            constructor create(var input : file);
22
            constructor create(var input : cfile);
23
            //destructor destroy; override;
23
            //destructor destroy; override;
24
24
25
            // retrieves a single character from input file and advances counters and stuff
25
            // retrieves a single character from input file and advances counters and stuff
...
...
30
            m_row   : size_t;
30
            m_row   : size_t;
31
            m_col   : size_t;
31
            m_col   : size_t;
32
        
32
        
33
            m_input : file of char;
33
            m_input : pcfile;
34
    end;
34
    end;
35
35
36
    islip_parser_token_type  = (
36
    islip_parser_token_type  = (
...
...
42
    // assembles read characters into proper tokens
42
    // assembles read characters into proper tokens
43
    islip_parser = class
43
    islip_parser = class
44
        public
44
        public
45
            constructor create(var input : file);
45
            constructor create(var input : cfile);
46
            //destructor destroy; override;
46
            //destructor destroy; override;
47
47
48
            // retrieves a single token
48
            // retrieves a single token
...
...
65
// islip_reader implementation
65
// islip_reader implementation
66
// ========================================================
66
// ========================================================
67
67
68
constructor islip_reader.create(var input : file);
68
constructor islip_reader.create(var input : cfile);
69
begin
69
begin
70
    m_input := input;
70
    m_input := @input;
71
    m_row := 0;
71
    m_row := 0;
72
    m_col := 0;
72
    m_col := 0;
73
end;
73
end;
...
...
77
    get_char := true;
77
    get_char := true;
78
78
79
    // check if there's anything left to read
79
    // check if there's anything left to read
80
    if eof(m_input) then begin
80
    if eof(m_input^) then begin
81
        get_char := false;
81
        get_char := false;
82
        exit;
82
        exit;
83
    end;
83
    end;
84
    read(m_input, c);
84
    read(m_input^, c);
85
    if ord(c) = 10 then begin
85
    if ord(c) = 10 then begin
86
        inc(m_row);
86
        inc(m_row);
87
        m_col := 0;
87
        m_col := 0;
...
...
99
// islip_parser implementation
99
// islip_parser implementation
100
// ========================================================
100
// ========================================================
101
101
102
constructor islip_parser.create(var input : file);
102
constructor islip_parser.create(var input : cfile);
103
begin
103
begin
104
    m_reader := islip_reader.create(input);
104
    m_reader := islip_reader.create(input);
105
    m_token := '';
105
    m_token := '';
...
...
116
    esc := false;
116
    esc := false;
117
117
118
    // if we still have a newline left over to throw, do it
118
    // if we still have a newline left over to throw, do it
119
    if m_token[1] in [chr(10), chr(13), ',', '.'] then begin
119
    if (length(m_token) = 1) and (m_token[1] in [chr(10), chr(13), ',']) then begin
120
        s := m_token;
120
        s := m_token;
121
        m_token[1] := chr(0);    // HACK HACK HACK! somehow necessary for the string to be zeroed
121
        m_token[1] := chr(0);    // HACK HACK HACK! somehow necessary for the string to be zeroed
122
        m_token := '';
122
        m_token := '';

Updated islip/typedefs.pas Download diff

56
13
    size_t  = cardinal; // basically an unsigned int
13
    size_t  = cardinal; // basically an unsigned int
14
    ushort  = word;     // unsigned short
14
    ushort  = word;     // unsigned short
15
15
16
    // these don't have anything to do with C, but they're here for convenience
17
    cfile   = file of char;
18
    pcfile  = ^cfile;
19
16
implementation
20
implementation
17
21
18
// nothing to see here, move along
22
// nothing to see here, move along

Updated islip/variable.pas Download diff

56
10
10
11
interface
11
interface
12
12
13
uses typedefs in 'typedefs.pas';
13
uses typedefs;
14
14
15
type
15
type
16
    islip_var_type  = (VT_UNTYPED, VT_INT, VT_FLOAT, VT_STRING, VT_ARRAY);
16
    islip_var_type  = (VT_UNTYPED, VT_INT, VT_FLOAT, VT_STRING, VT_ARRAY);