Kestrel-3

Check-in [0dda2d09e7]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Basic .dword primitive
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256:0dda2d09e7661fa4899e647ea3297c386053647aeba84773111c1c2da9426c5b
User & Date: kc5tja 2019-09-03 01:29:54
Context
2019-09-03
02:07
String expression support check-in: 88de4ec636 user: kc5tja tags: trunk
01:29
Basic .dword primitive check-in: 0dda2d09e7 user: kc5tja tags: trunk
2019-09-02
23:11
First parser integration test check-in: 9688a01a13 user: kc5tja tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to dev/src/bcpl/assemrv/globals_utils.h.

1
2
3
4

5
GLOBAL {
    zerovec : g_utils;
    max;
    streq;

}




>

1
2
3
4
5
6
GLOBAL {
    zerovec : g_utils;
    max;
    streq;
    copystr;
}

Changes to dev/src/bcpl/assemrv/manifest.h.

3
4
5
6
7
8
9
10
11


12
13
14
15
16
17
18
19
..
50
51
52
53
54
55
56

















57
58
59
60
61
62
63
    // This might one day be a parameter.
    failat           = 20;

    // These are stuffed into result2 to give the developer a crude
    // indication of why a test failed.  Ideally, these should be
    // taken from standard BCPL/Tripos error result codes as much as
    // possible.  For now, though, they're proprietary.
    err_no_memory    = 1;
    err_overflow     = 2;


    err_field        = 50000;		// Record field (n - err_field) not of expected value

    // Hunk format executables use these constants.
    HUNK_END         = 5000;
    HUNK_CODE;

    // Global Vector Constants
    g_sections       = ug + 100;
................................................................................
    sc_col;
    sc_sym;
    sc_ch;
    sc_label;
    sc_value;
    sc_keywords;
    sc_sizeof;


















    // Scanner symbol types
    scs_char_upb = 255;
    scs_identifier;
    scs_byte;
    scs_2byte;
    scs_4byte;







|
|
>
>
|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
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
    // This might one day be a parameter.
    failat           = 20;

    // These are stuffed into result2 to give the developer a crude
    // indication of why a test failed.  Ideally, these should be
    // taken from standard BCPL/Tripos error result codes as much as
    // possible.  For now, though, they're proprietary.
    err_no_memory        = 1;
    err_overflow         = 2;
    err_syntax_error     = 100;		// Generic syntax error
    err_int_expr_expected;
    err_field            = 50000;	// Record field (n - err_field) not of expected value

    // Hunk format executables use these constants.
    HUNK_END         = 5000;
    HUNK_CODE;

    // Global Vector Constants
    g_sections       = ug + 100;
................................................................................
    sc_col;
    sc_sym;
    sc_ch;
    sc_label;
    sc_value;
    sc_keywords;
    sc_sizeof;

    // Error Descriptor fields
    ed_next = 0;
    ed_filename;
    ed_line;
    ed_col;
    ed_code;
    ed_sizeof;

    // Expression Descriptor fields
    expr_type = 0;
    expr_value;
    expr_sizeof;

    // Expression Types
    et_unknown = 0;
    et_integer;

    // Scanner symbol types
    scs_char_upb = 255;
    scs_identifier;
    scs_byte;
    scs_2byte;
    scs_4byte;

Changes to dev/src/bcpl/assemrv/parser.b.

1











































2
3
4
5
6













LET parse(s, d) BE {











































	dynvec_put_at(d, IR_LIT, 0)
	dynvec_put_at(d, 1, 1)
	dynvec_put_at(d, IR_DWORD, 2)
}














|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
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
LET parse(s, d, errp) BE {
	LET sym = scanner_sym(s)

	// Don't even try unless a chain of errors can be constructed.
	UNLESS errp DO RETURN

	IF sym = scs_dword DO scanner_next(s) <> dword(s, d, errp) <> RETURN

	error(errp, s, err_syntax_error)
}

AND error(errp, scanner, errcode) BE {
	LET errdesc = getvec(ed_sizeof)
	IF errdesc DO {
		zerovec(errdesc, ed_sizeof)
		errdesc!ed_filename := copystr(scanner_filename(scanner))
		errdesc!ed_line := scanner_line(scanner)
		errdesc!ed_col := scanner_col(scanner)
		errdesc!ed_code := errcode

		errdesc!ed_next := !errp
		!errp := errdesc
	}
}

AND dword(s, d, errp) BE {
	LET expr = VEC expr_sizeof

	zerovec(expr, expr_sizeof)

	dword_part(s, d, errp, expr)
	IF !errp DO RETURN
	WHILE scanner_sym(s) = ',' DO {
		scanner_next(s)
		dword_part(s, d, errp, expr)
		IF !errp DO RETURN
	}
}

AND dword_part(s, d, errp, expr) BE {
	expression(s, d, errp, expr)
	IF !errp DO RETURN
	IF expr!expr_type ~= et_integer DO error(errp, s, err_int_expr_expected) <> RETURN

	dynvec_put_at(d, IR_LIT, d!dv_length)
	dynvec_put_at(d, expr!expr_value, d!dv_length)
	dynvec_put_at(d, IR_DWORD, d!dv_length)

}

AND expression(s, d, errp, expr) BE {
	LET sym = scanner_sym(s)

	IF sym = scs_integer DO {
		expr!expr_type := et_integer
		expr!expr_value := scanner_value(s)
		scanner_next(s)
		RETURN
	}

	error(errp, s, err_syntax_error)
}

Changes to dev/src/bcpl/assemrv/test_parser.b.

43
44
45
46
47
48
49


50
51
52
53
54
55
56
..
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
..
94
95
96
97
98
99
100
101

102
103
104
105
106
107
























































108
109
110
111
112
113
114
115
116

SECTION "parser"

GET "libhdr"
GET "manifest"
GET "globals_dynvec"
GET "globals_parser"


GET "parser.b"
.

SECTION "test_parser"

GET "libhdr"
GET "manifest"
................................................................................
GET "globals_dynvec"
GET "globals_scanner"
GET "globals_utils"
GET "globals_parser"


LET testlist() = VALOF {
	MANIFEST { ntests = 1 }
	LET tl = getvec(ntests)
	tl!0 := ntests
	tl!1 := test_single_dword

	RESULTIS tl
}


// Parser Tests: Simple listings

AND test_single_dword(r) = VALOF {
	LET err = failat
	LET scb, s, d = 0, 0, 0


	IF r DO RESULTIS r
	testid := "test_single_dword"

	scb := findinoutput("RAM:")
	UNLESS NEQ(scb, 0, 0) DO GOTO unwind
	{
................................................................................
	UNLESS EQ(scanner_get_stream(s, scb, "RAM:"), TRUE, 3) DO GOTO unwind
	scanner_nextchar(s)
	scanner_next(s)

	d := make_dynvec()
	UNLESS NEQ(d, 0, 4) DO GOTO unwind

	parse(s, d)


	UNLESS EQ(d!dv_length, 3, 100) DO GOTO unwind
	UNLESS EQ(dynvec_at(d, 0), IR_LIT, 101) DO GOTO unwind
	UNLESS EQ(dynvec_at(d, 1), 1, 102) DO GOTO unwind
	UNLESS EQ(dynvec_at(d, 2), IR_DWORD, 103) DO GOTO unwind

























































	err := 0

unwind:
	IF d DO dynvec_free(d)
	IF s DO scanner_free(s)
	IF scb DO endstream(scb)
	RESULTIS err
}








>
>







 







|



>









>







 







|
>






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
..
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
..
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177

SECTION "parser"

GET "libhdr"
GET "manifest"
GET "globals_dynvec"
GET "globals_parser"
GET "globals_scanner"
GET "globals_utils"
GET "parser.b"
.

SECTION "test_parser"

GET "libhdr"
GET "manifest"
................................................................................
GET "globals_dynvec"
GET "globals_scanner"
GET "globals_utils"
GET "globals_parser"


LET testlist() = VALOF {
	MANIFEST { ntests = 2 }
	LET tl = getvec(ntests)
	tl!0 := ntests
	tl!1 := test_single_dword
	tl!2 := test_single_dword_chain
	RESULTIS tl
}


// Parser Tests: Simple listings

AND test_single_dword(r) = VALOF {
	LET err = failat
	LET scb, s, d = 0, 0, 0
	LET errlist = 0

	IF r DO RESULTIS r
	testid := "test_single_dword"

	scb := findinoutput("RAM:")
	UNLESS NEQ(scb, 0, 0) DO GOTO unwind
	{
................................................................................
	UNLESS EQ(scanner_get_stream(s, scb, "RAM:"), TRUE, 3) DO GOTO unwind
	scanner_nextchar(s)
	scanner_next(s)

	d := make_dynvec()
	UNLESS NEQ(d, 0, 4) DO GOTO unwind

	parse(s, d, @errlist)
	UNLESS EQ(errlist, 0, 5) DO GOTO unwind

	UNLESS EQ(d!dv_length, 3, 100) DO GOTO unwind
	UNLESS EQ(dynvec_at(d, 0), IR_LIT, 101) DO GOTO unwind
	UNLESS EQ(dynvec_at(d, 1), 1, 102) DO GOTO unwind
	UNLESS EQ(dynvec_at(d, 2), IR_DWORD, 103) DO GOTO unwind

	err := 0

unwind:
	IF errlist DO free_errors(errlist)
	IF d DO dynvec_free(d)
	IF s DO scanner_free(s)
	IF scb DO endstream(scb)
	RESULTIS err
}

AND free_errors(p) BE {
	WHILE p DO {
		LET dsc = p
		p := dsc!ed_next
		IF dsc!ed_filename DO freevec(dsc!ed_filename)
		freevec(dsc)
	}
}

AND test_single_dword_chain(r) = VALOF {
	LET err = failat
	LET scb, s, d = 0, 0, 0
	LET expected = TABLE IR_LIT, 1, IR_DWORD,
	                     IR_LIT, 2, IR_DWORD,
	                     IR_LIT, 3, IR_DWORD,
	                     IR_LIT, 4, IR_DWORD
	LET errlist = 0

	IF r DO RESULTIS r
	testid := "test_single_dword_chain"

	scb := findinoutput("RAM:")
	UNLESS NEQ(scb, 0, 0) DO GOTO unwind
	{
		LET outs = output()
		selectoutput(scb)
		writef(".dword 1, 2, 3, 4*n")
		selectoutput(outs)
		rewindstream(scb)
	}

	s := make_scanner()
	UNLESS NEQ(s, 0, 1) DO GOTO unwind
	UNLESS EQ(scanner_get_stream(s, scb, "RAM:"), TRUE, 3) DO GOTO unwind
	scanner_nextchar(s)
	scanner_next(s)

	d := make_dynvec()
	UNLESS NEQ(d, 0, 4) DO GOTO unwind

	parse(s, d, @errlist)
	UNLESS EQ(errlist, 0, 5) DO GOTO unwind

	UNLESS EQ(d!dv_length, 12, 100) DO GOTO unwind
	FOR i = 0 TO 11 DO UNLESS EQ(dynvec_at(d, i), expected!i, 200+i) DO GOTO unwind

	err := 0

unwind:
	IF d DO dynvec_free(d)
	IF s DO scanner_free(s)
	IF scb DO endstream(scb)
	RESULTIS err
}

Changes to dev/src/bcpl/assemrv/utils.b.

13
14
15
16
17
18
19






AND streq(actual, expected) = VALOF {
    UNLESS actual%0 = expected%0 DO RESULTIS FALSE
    FOR i = 1 TO actual%0 DO UNLESS actual%i = expected%i DO RESULTIS FALSE
    RESULTIS TRUE
}













>
>
>
>
>
13
14
15
16
17
18
19
20
21
22
23
24

AND streq(actual, expected) = VALOF {
    UNLESS actual%0 = expected%0 DO RESULTIS FALSE
    FOR i = 1 TO actual%0 DO UNLESS actual%i = expected%i DO RESULTIS FALSE
    RESULTIS TRUE
}

AND copystr(src) = VALOF {
    LET dst = getvec((src%0 >> B2Wsh)+1)
    IF dst DO FOR i = 0 TO src%0 DO dst%i := src%i
    RESULTIS dst
}