Check-in [67f834abb0]
Bounty program for improvements to Tcl and certain Tcl packages.

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

Overview
Comment:Account for emptiness in LIST and DICT types
Timelines: family | ancestors | descendants | both | list-and-dict-types
Files: files | file ages | folders
SHA3-256: 67f834abb0e09869a97256725da57ff6f29c985a217c80978ad2ee83893c773a
User & Date: dkf 2018-11-28 08:31:46
Context
2018-11-28
08:52
Default type conversions. check-in: 7a7e53d026 user: dkf tags: list-and-dict-types
08:31
Account for emptiness in LIST and DICT types check-in: 67f834abb0 user: dkf tags: list-and-dict-types
2018-11-27
13:48
Also assert that DICT has a 'free' conversion to LIST check-in: 7de430014e user: dkf tags: list-and-dict-types
Changes

Changes to codegen/compile.tcl.

1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
    #	leak or triggers use-after-free crashes. Leave that to the main
    #	compiler engine (and the STRING allocator) as that gets it right.

    method LoadTypedLiteral {value type} {
	if {[lindex $type 0] eq "IMPURE"} {
	    set sval [my LoadTypedLiteral $value STRING]
	    set itype [lrange $type 1 end]
	    if {$itype in {LIST DICT}} {
		return $sval
	    }
	    set tval [my LoadTypedLiteral $value $itype]
	    return [$b impure $itype $sval $tval]
	} elseif {$type eq "DOUBLE"} {
	    return [ConstReal [Type $type] $value]
	} elseif {$type in {"ZEROONE" "BOOLEAN" "ZEROONE BOOLEAN"}} {
	    return [Const [expr {$value}] bool]
	} elseif {$type in {"INT" "ENTIER"}} {
	    return [$b int [expr {entier($value)}]]
	} elseif {$type in {"STRING" "LIST" "DICT" "EMPTY"}} {
	    set result [Const $value STRING]
	    $b assume [$b shared $result]
	    return $result
	} else {
	    return -code error \
		"unhandled type for literal \"${value}\": \"$type\""
	}






|










|







1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
    #	leak or triggers use-after-free crashes. Leave that to the main
    #	compiler engine (and the STRING allocator) as that gets it right.

    method LoadTypedLiteral {value type} {
	if {[lindex $type 0] eq "IMPURE"} {
	    set sval [my LoadTypedLiteral $value STRING]
	    set itype [lrange $type 1 end]
	    if {$itype in {LIST DICT {EMPTY LIST} {EMPTY DICT}}} {
		return $sval
	    }
	    set tval [my LoadTypedLiteral $value $itype]
	    return [$b impure $itype $sval $tval]
	} elseif {$type eq "DOUBLE"} {
	    return [ConstReal [Type $type] $value]
	} elseif {$type in {"ZEROONE" "BOOLEAN" "ZEROONE BOOLEAN"}} {
	    return [Const [expr {$value}] bool]
	} elseif {$type in {"INT" "ENTIER"}} {
	    return [$b int [expr {entier($value)}]]
	} elseif {$type in {"STRING" "LIST" "DICT" "EMPTY" "EMPTY LIST" "EMPTY DICT"}} {
	    set result [Const $value STRING]
	    $b assume [$b shared $result]
	    return $result
	} else {
	    return -code error \
		"unhandled type for literal \"${value}\": \"$type\""
	}

Changes to codegen/struct.tcl.

2809
2810
2811
2812
2813
2814
2815
2816



2817
2818
2819
2820
2821



2822
2823
2824



2825
2826









2827
2828
2829
2830
2831
2832
2833
	    }
	    {{EXPANDED NUMERIC} NUMERIC} {
		append body2 { $} [lindex $f 0]
	    }
	    {{EXPANDED {NUMERIC BOOLEAN}} {NUMERIC BOOLEAN}} {
		append body2 { $} [lindex $f 0]
	    }
	    {{INPURE DICT} STRING} {



		append body2 { $} [lindex $f 0]
	    }
	    {DICT STRING} {
		append body2 { $} [lindex $f 0]
	    }



	    {{IMPURE LIST} STRING} {
		append body2 { $} [lindex $f 0]
	    }



	    {DICT LIST} {
		append body2 { $} [lindex $f 0]









	    }
	}

	foreach type {
	    BOOLEAN
	    ZEROONE {ZEROONE BOOLEAN}
	    INT {INT BOOLEAN}






|
>
>
>





>
>
>



>
>
>


>
>
>
>
>
>
>
>
>







2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
	    }
	    {{EXPANDED NUMERIC} NUMERIC} {
		append body2 { $} [lindex $f 0]
	    }
	    {{EXPANDED {NUMERIC BOOLEAN}} {NUMERIC BOOLEAN}} {
		append body2 { $} [lindex $f 0]
	    }
	    {{IMPURE DICT} STRING} {
		append body2 { $} [lindex $f 0]
	    }
	    {{IMPURE EMPTY DICT} STRING} {
		append body2 { $} [lindex $f 0]
	    }
	    {DICT STRING} {
		append body2 { $} [lindex $f 0]
	    }
	    {{EMPTY DICT} STRING} {
		append body2 { $} [lindex $f 0]
	    }
	    {{IMPURE LIST} STRING} {
		append body2 { $} [lindex $f 0]
	    }
	    {{IMPURE EMPTY LIST} STRING} {
		append body2 { $} [lindex $f 0]
	    }
	    {DICT LIST} {
		append body2 { $} [lindex $f 0]
	    }
	    {{EMPTY DICT} {EMPTY LIST}} {
		append body2 { $} [lindex $f 0]
	    }
	    {{IMPURE DICT} {IMPURE LIST}} {
		append body2 { $} [lindex $f 0]
	    }
	    {{IMPURE EMPTY DICT} {IMPURE EMPTY LIST}} {
		append body2 { $} [lindex $f 0]
	    }
	}

	foreach type {
	    BOOLEAN
	    ZEROONE {ZEROONE BOOLEAN}
	    INT {INT BOOLEAN}

Changes to codegen/tycon.tcl.

69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
...
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
		    return [ConstInt [Type bool] 1 0]
		}
		if {[string is false -strict $value]} {
		    return [ConstInt [Type bool] 0 0]
		}
		error "invalid boolean value \"$value\""
	    }
	    "^STRING$" - "^LIST$" - "^DICT$" - "^EMPTY$" {
		variable thunkBuilder
		set theObj [$thunkBuilder obj.constant $value]
		return $theObj
	    }
	    {^LLVMTypeRef_\d+$} {
		switch [GetTypeKind $type] {
		    LLVMIntegerTypeKind {
................................................................................
	    ^long$ {
		# Machine word
		return [IntType [expr {$::tcl_platform(wordSize) * 8}]]
	    }
	    {^int(\d+)$} {
		return [IntType [lindex $m 1]]
	    }
	    ^STRING$ - ^LIST$ - ^DICT$ - ^EMPTY$ {
		return [Type named{Tcl_Obj}*]
	    }
	    ^ZEROONE$ - ^BOOLEAN$ - "^ZEROONE BOOLEAN$" {
		return [Type bool]
	    }
	    ^INT$ - ^ENTIER$ - "^INT BOOLEAN$" {
		return [Type named{INT,kind:int1,i32:int,i64:int64}]






|







 







|







69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
...
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
		    return [ConstInt [Type bool] 1 0]
		}
		if {[string is false -strict $value]} {
		    return [ConstInt [Type bool] 0 0]
		}
		error "invalid boolean value \"$value\""
	    }
	    "^STRING$" - "^(?:EMPTY )?(?:LIST|DICT)$" - "^EMPTY$" {
		variable thunkBuilder
		set theObj [$thunkBuilder obj.constant $value]
		return $theObj
	    }
	    {^LLVMTypeRef_\d+$} {
		switch [GetTypeKind $type] {
		    LLVMIntegerTypeKind {
................................................................................
	    ^long$ {
		# Machine word
		return [IntType [expr {$::tcl_platform(wordSize) * 8}]]
	    }
	    {^int(\d+)$} {
		return [IntType [lindex $m 1]]
	    }
	    ^STRING$ - {^(EMPTY )?(LIST|DICT)$} - ^EMPTY$ {
		return [Type named{Tcl_Obj}*]
	    }
	    ^ZEROONE$ - ^BOOLEAN$ - "^ZEROONE BOOLEAN$" {
		return [Type bool]
	    }
	    ^INT$ - ^ENTIER$ - "^INT BOOLEAN$" {
		return [Type named{INT,kind:int1,i32:int,i64:int64}]

Changes to quadcode/types.tcl.

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
...
381
382
383
384
385
386
387

388
389
390
391
392
393
394
    variable NUMERIC		[expr {$DOUBLE | $ENTIER}]

    # NUMERIC_OR_BOOLEAN - the value is a number, or some spelling of
    #                      'true' or 'false'

    variable NUMERIC_OR_BOOLEAN	[expr {$NUMERIC | $BOOLEAN}]

    # DICT - the value is a dictionary of some sort. The types of the keys and
    #		the values are just STRING.

    variable DICT		[expr 0x200]

    # LIST - the value is a list of some sort that isn't a dictionary. The
    #		type of the elements is just STRING.

    variable NONDICTLIST	[expr 0x100]

    # LIST - the value is a list of some sort. The type of the elements is
    #		just STRING. Note that a DICT is also a LIST.

    variable LIST		[expr {$NONDICTLIST | $DICT}]






    # FOREACH - the value represents the iterator of a [foreach] or [lmap].
    #           There are no constants of this type, and it is therefore
    #           always pure.

    variable FOREACH		[expr 0x10000]

................................................................................
	DOUBLE		DOUBLE
	BIGINT		ENTIER
	OTHERINT64	INT
	OTHERINT32	INT
	ZEROONE		ZEROONE
	BOOLWORD	BOOLEAN
	NONDICTLIST	LIST

	DICT		DICT
	LIST		LIST
    } {
	namespace upvar dataType $name t
	if {$type & $t} {
	    namespace upvar dataType $wname w
	    lappend result $wname






|
|

|

|
|






|
>
>
>
>
>







 







>







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
...
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
    variable NUMERIC		[expr {$DOUBLE | $ENTIER}]

    # NUMERIC_OR_BOOLEAN - the value is a number, or some spelling of
    #                      'true' or 'false'

    variable NUMERIC_OR_BOOLEAN	[expr {$NUMERIC | $BOOLEAN}]

    # NONEMPTYDICT - the value is a non-empty dictionary of some sort. The
    #		types of the keys and the values are just STRING.

    variable NONEMPTYDICT	[expr 0x200]

    # NONDICTLIST - the value is a list of some sort that isn't a dictionary
    #		but isn't empty. The type of the elements is just STRING.

    variable NONDICTLIST	[expr 0x100]

    # LIST - the value is a list of some sort. The type of the elements is
    #		just STRING. Note that a DICT is also a LIST.

    variable LIST		[expr {$NONDICTLIST | $NONEMPTYDICT | $EMPTY}]

    # DICT - the value is a dict of some sort. The type of the keys and values
    #		are just STRING. Note that a DICT is also a LIST.

    variable DICT		[expr {$NONEMPTYDICT | $EMPTY}]

    # FOREACH - the value represents the iterator of a [foreach] or [lmap].
    #           There are no constants of this type, and it is therefore
    #           always pure.

    variable FOREACH		[expr 0x10000]

................................................................................
	DOUBLE		DOUBLE
	BIGINT		ENTIER
	OTHERINT64	INT
	OTHERINT32	INT
	ZEROONE		ZEROONE
	BOOLWORD	BOOLEAN
	NONDICTLIST	LIST
	NONEMPTYDICT	DICT
	DICT		DICT
	LIST		LIST
    } {
	namespace upvar dataType $name t
	if {$type & $t} {
	    namespace upvar dataType $wname w
	    lappend result $wname