uCBQN/test/cases/ffi.bqn
2024-02-04 23:19:57 +02:00

259 lines
19 KiB
BQN
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

%DEF var V•internal.Variation LV•internal.ListVariations CLR•internal.ClearRefs
%DEF tvar %USE var _tvar {F _𝕣 x: (CLR@) {F 𝕩 V x}¨ LV 𝕩; w F _𝕣 x: (CLR@) (LV 𝕨) {(𝕨 V w) F 𝕩 V x} LV 𝕩}
%DEF defs size_t "u64" size_tw 64
# bad •FFI invocation
# generally weird
!"•FFI: Path must be a list of characters" % 12 •FFI """bqn_init"
!"This function can't be called monadically" % •FFI """bqn_init"
@ •FFI{𝕊: 28•CurrentError@} """bqn_this symbol doesn't exist" %% "FFI: Failed to find symbol: "
!"FFI: Type must be a string" % @•FFI "hello"
!"FFI: Too many arguments" % @•FFI"""bqn_init"70000<"i32"
!"Type parser: Unexpected character '?'" % @•FFI"""bqn_init""?"
!"Type parser: Bad array type" % @•FFI"""bqn_init""["
!"Type parser: Bad array type" % @•FFI"""bqn_init""[0"
!"Type parser: Unexpected end of input" % @•FFI"""bqn_init""[1]"
!"Type parser: Unexpected end of input" % @•FFI"""bqn_init""{"
!"Type parser: Bad integer width" % @•FFI"""bqn_init""i"
!"Type parser: Bad float width" % @•FFI"""bqn_init""f80"
!"Type parser: Bad float width" % @•FFI"""bqn_init""f128"
!"Type parser: Bad float width" % @•FFI"""bqn_init""f16"
!"Type parser: Bad float width" % @•FFI"""bqn_init""f1"
!"Type parser: Bad integer width" % @•FFI"""bqn_init""u1"
!"Type parser: Bad integer width" % @•FFI"""bqn_init""i0"
!"Type parser: Bad integer width" % @•FFI"""bqn_init""i10"
!"Type parser: Bad integer width" % @•FFI"""bqn_init""u128"
!"Type parser: Type was empty" % @•FFI"""bqn_init"""
!"Type parser: number literal too large" % @•FFI"""bqn_init""u99999999999999"
# >/𝕨/𝕩
!"FFI: Multiple occurrences of '>' within one argument" % @•FFI"""bqn_init"">>i32"
!"FFI: Multiple occurrences of argument side specified" % @•FFI"""bqn_init""𝕨𝕨i32"
!"FFI: Multiple occurrences of argument side specified" % @•FFI"""bqn_init""𝕩𝕩i32"
!"FFI: Multiple occurrences of argument side specified" % @•FFI"""bqn_init""𝕨𝕩i32"
!"FFI: Multiple arguments on 𝕩 specified, some with '>'" % @•FFI"""bqn_init"">i32"">i32"
!"FFI: Multiple arguments on 𝕨 specified, some with '>'" % @•FFI"""bqn_init"">𝕨i32"">𝕨i32"
!"FFI: Multiple arguments on 𝕩 specified, some with '>'" % @•FFI"""bqn_init"">i32""i32"
!"FFI: Multiple arguments on 𝕨 specified, some with '>'" % @•FFI"""bqn_init"">𝕨i32""𝕨i32"
# arrays
!"Type parser: 0-item arrays not supported" % @•FFI"""bqn_init""[0]i32"
!"Type parser: number literal too large" % @•FFI"""bqn_init""[999999999999]i32"
!"Type parser: Top-level array too large; limit is 65535 elements" % @•FFI"""bqn_init""[65536]i32"
!"Type parser: Top-level array too large; limit is 65535 elements" % @•FFI"""bqn_init""[4000000000]i32"
!"Type parser: Array too large; limit is 65534 bytes" % @•FFI"""bqn_init""*[20000]i32"
!"FFI: Cannot return array" % @•FFI"[4]i32""bqn_init"
# structs
!"Type parser: Improper struct separator or end" % @•FFI"""bqn_init""{*i32*i32}"
!"Type parser: Improper struct separator or end" % @•FFI"""bqn_init""{*i32"
!"Type parser: Unexpected end of input" % @•FFI"""bqn_init""{*i32,"
!"Type parser: Structs currently cannot contain mutable references" % @•FFI"""bqn_init""{&i32}"
# !"Type parser: Structs currently cannot contain mutable references" % @•FFI""‿"bqn_init"‿"{[2]&i32}" # TODO
# :
!"Type parser: Unexpected character after "":""" % @•FFI"""bqn_init""i32:"
!"Type parser: Unexpected character after "":""" % f@•FFI"""bqn_init"">*u64:q8"
!"Type parser: Unsupported width in :i0" % @•FFI"""bqn_init""i32:i"
!"Type parser: Unsupported width in :i9" % @•FFI"""bqn_init""i32:i9"
!"Type parser: Unsupported width in :u16" % @•FFI"""bqn_init""i32:u16"
!"Type parser: Unsupported width in :i64" % @•FFI"i32:i64""bqn_init"
!"Type parser: Unsupported width in :f32" % @•FFI"""bqn_init""i32:f32"
!"Type parser: number literal too large" % @•FFI"""bqn_init""i32:u9999999999999999"
!"Type parser: Representation wider than the value for ""i32:f64""" % @•FFI"""bqn_init""i32:f64"
!"Type parser: Garbage at end of type" % @•FFI"""bqn_init""i32 hello world"
# return value
!"FFI: Function specification must have at least two items" % @•FFI "&"
!"FFI: Return value is specified as ""&"", but there are 0 mutated values" % @•FFI"&""bqn_init"">*i32"
!"FFI: Return value is specified as ""&"", but there are 2 mutated values" % @•FFI"&""bqn_init""&i32""&i32"
!"FFI: Cannot return array" % @•FFI"[4]i32""bqn_init"
# correct elements
%USE defs f@•FFI"&""memcpy""&u8""*i8"size_t G{F𝕩,0,0} %USE tvar !¨ G _tvar 10010
%USE defs f@•FFI"&""memcpy""&u8""*i8"size_t G{F𝕩,0,0} G 200 %% 200
%USE defs f@•FFI"&""memcpy""&u16""*i8"size_t G{F𝕩,0,0} G 65535 %% 65535
%USE defs f@•FFI"&""memcpy""&u32""*i8"size_t G{F𝕩,0,0} G (232)|¯5+10 %% (232)|¯5+10
%USE defs f@•FFI"&""memcpy""&i16""*i8"size_t G{F𝕩,0,0} G ¯3276832767 %% ¯3276832767
%USE defs f@•FFI"&""memcpy""&{i16}""*i8"size_t G{F𝕩,0,0} G ¨¯3276832767 %% ¨¯3276832767
%USE defs f@•FFI"&""memcpy""&f32""*i8"size_t G{F𝕩,0,0} G ,¯∞,÷10÷˜10 %% ,¯∞,÷00.100000001490116120.200000002980232240.300000011920928960.40000000596046450.50.60000002384185790.6999999880790710.8000000119209290.8999999761581421
%USE defs f@•FFI"&""memcpy""&i32""*i16:u1"size_t F 5, 321, 4 %% ¯1
%USE defs f@•FFI"&","memcpy","&i8","*i8",size_t":u1" F ¯100+10, 10, size_tw001 %% (4)4¯100+10
%USE defs f@•FFI"&""memcpy""&i16""*i16:i32"size_t F ¯100+10, 123+456×216, ¯2, 8 %% 123456¯2¯14¯100+10
%USE defs f@•FFIsize_t,"strlen","*i8" F 1230 %% 3
%USE defs f@•FFI"&","memcpy","&i8","[4]i8",size_t F 100, 3+4, 4 %% 3456000000
# bad array elements
!"Type parser: Structs currently cannot contain mutable references" % size_t "u64" size_tw 64 f@•FFI"&""memcpy""&{&i16}""*i8"size_t G{F𝕩,0,0} G ¨¯3276832767
!"FFI: Array provided for &u8 contained 299" % f@•FFI"&""bqn_init"">&u8" F 300
!"FFI: Array provided for &u8 contained ¯99" % f@•FFI"&""bqn_init"">&u8" F -100
!"FFI: Array provided for &u16 contained 65536" % f@•FFI"&""bqn_init"">&u16" F 65536
!"FFI: Array provided for &u32 contained 4294967296" % f@•FFI"&""bqn_init"">&u32" F 232
!"FFI: Array provided for &u16 contained ¯1" % f@•FFI"&""bqn_init"">&u16" F ¯1
!"FFI: Array provided for &u32 contained ¯1" % f@•FFI"&""bqn_init"">&u32" F ¯1
# bad scalars
!"FFI: improper value for u8" % f@•FFI"""bqn_init"">u8" F 256
!"FFI: improper value for u16" % f@•FFI"""bqn_init"">u16" F ¯1
!"FFI: improper value for u32" % f@•FFI"""bqn_init"">u32" F ¯1
!"FFI: improper value for u64" % f@•FFI"""bqn_init"">u64" F ¯1
!"FFI: improper value for u32" % f@•FFI"""bqn_init"">u32" F 232
!"FFI: improper value for u32" % f@•FFI"""bqn_init"">u32" F 1e20
!"FFI: u64 argument value ≥ 2⋆53" % f@•FFI"""bqn_init"">u64" F 253
!"FFI: i64 argument absolute value ≥ 2⋆53" % f@•FFI"""bqn_init"">i64" F 253
!"FFI: i64 argument absolute value ≥ 2⋆53" % f@•FFI"""bqn_init"">i64" F -253
!"FFI: improper value for i32" % f@•FFI"""bqn_init"">𝕨i32"">i64" @ F 3
!"FFI: improper value for i32" % f@•FFI"""bqn_init"">𝕨i32"">i64" 1 F 3
!"FFI: improper value for i64" % f@•FFI"""bqn_init""i64" F @
# bad overall argument separation
!"FFI: Expected list 𝕩" % f@•FFI"""bqn_init""i32""i32" F @
!"FFI: Expected list 𝕩" % f@•FFI"""bqn_init""i32""i32" F 2, 2
!"FFI: Expected list 𝕨" % f@•FFI"""bqn_init""𝕨i32""𝕨i32" (12) F
!"FFI: Wrong argument count in 𝕩: expected 2, got 3" % f@•FFI"""bqn_init""i32""i32" F 2, 2, 2
!"FFI: Wrong argument count in 𝕩: expected 2, got 1" % f@•FFI"""bqn_init""i32""i32" F 2
!"FFI: Wrong argument count in 𝕨: expected 2, got 3" % f@•FFI"""bqn_init""i32""𝕨i32""𝕨i32" 2, 2, 2 F 4
!"FFI: 𝕩 must be an empty list" % f@•FFI"""bqn_init" F 1
!"FFI: 𝕩 must be an empty list" % f@•FFI"""bqn_init" F @
!"FFI: 𝕩 must be an empty list" % f@•FFI"""bqn_init""𝕨i32""𝕨i32" 12 F @
!"FFI: 𝕨 must either be an empty list, or not be present" % f@•FFI"""bqn_init""*i8" 1,2 F 1230
!"FFI: 𝕨 must either be an empty list, or not be present" % f@•FFI"""bqn_init""*i8" @ F 1230
!"FFI: 𝕨 must be present" % f@•FFI"""bqn_init""𝕨i32""𝕨i32" F
!"FFI: 𝕨 must be present" % f@•FFI"""bqn_init""𝕨i32""i32" F 3
!"FFI: 𝕨 must be present" % f@•FFI"""bqn_init"">𝕨i32"">i32" F 3
# wrong argument internal structure
!"FFI: Expected array corresponding to *{...}" % f@•FFI"""bqn_init"">*{i32}" F @
!"FFI: Expected array corresponding to a struct" % f@•FFI"""bqn_init"">{i32}" F @
!"FFI: Expected array corresponding to a struct" % f@•FFI"""bqn_init"">*{i32}" F @
!"FFI: Incorrect list length corresponding to a struct: expected 1, got 0" % f@•FFI"""bqn_init"">*{i32}" F
!"FFI: Incorrect list length corresponding to a struct: expected 1, got 2" % f@•FFI"""bqn_init"">*{i32}" F 12
!"FFI: Incorrect list length corresponding to an array: expected 2, got 0" % f@•FFI"""bqn_init"">*[2]i32" F
!"FFI: Incorrect list length corresponding to an array: expected 2, got 3" % f@•FFI"""bqn_init"">*[2]i32" F 123
# bad :
!"FFI: Expected array corresponding to ""i32:i8""" % f@•FFI"""bqn_init"">i32:i8" F @
!"FFI: Expected array corresponding to ""*i32:i8""" % f@•FFI"""bqn_init"">*i32:i8" F @
!"FFI: Bad array corresponding to ""i32:i8"": expected 4 elements, got 10" % f@•FFI"""bqn_init"">i32:i8" F 10
!"FFI: Bad array corresponding to ""u64:u1"": expected 64 elements, got 128" % f@•FFI"""bqn_init"">u64:u1" F 1281
!"FFI: Array provided for :u1 contained 63" % f@•FFI"""bqn_init"">u64:u1" F 64
!"FFI: Bad array corresponding to ""u64:i8"": expected 8 elements, got 64" % f@•FFI"""bqn_init"">u64:i8" F 64
!"FFI: Expected array corresponding to ""*u64:i8""" % f@•FFI"""bqn_init"">*u64:i8" F @
!"FFI: Array provided for :i8 contained 199" % f@•FFI"""bqn_init"">*u64:i8" F 200
!"FFI: Array provided for :i8 contained 199" % f@•FFI"""bqn_init"">&u64:i8" F 200
!"FFI: Array provided for :u1 contained 63" % f@•FFI"""bqn_init"">&u64:u1" F 64
!"FFI: Bad array corresponding to ""*u64:i8"": expected a multiple of 8 elements, got 2" % f@•FFI"""bqn_init"">*u64:i8" F 2
!"FFI: Bad array corresponding to ""*u32:i16"": expected a multiple of 2 elements, got 1" % f@•FFI"""bqn_init"">*u32:i16" F 1
!"FFI: Bad array corresponding to ""&u64:u1"": expected a multiple of 64 elements, got 32" % f@•FFI"""bqn_init"">&u64:u1" F 320
!"FFI: Array provided for &i16 contained 32768" % f@•FFI"&""bqn_init"">&i16" F ¯3276832768
!"FFI: Array provided for &i16 contained ¯32769" % f@•FFI"&""bqn_init"">&i16" F ¯32768¯32769
!"FFI: Array provided for &u8 contained an array" % f@•FFI"&""bqn_init"">&u8" F 300
!"FFI: Array provided for &i16 contained a character" % f@•FFI"&""bqn_init"">&i16" F "hi"
!"FFI: Array provided for &f64 contained a namespace" % f@•FFI"&""bqn_init"">&f64" F 12{}
# unimplemented stuff
!"FFI: ""*i64"" argument type not yet implemented" % f@•FFI"""bqn_init"">&i64" F 10
!"FFI: ""*i64"" argument type not yet implemented" % f@•FFI"""bqn_init"">*i64" F 10
!"FFI: ""*u64"" argument type not yet implemented" % f@•FFI"""bqn_init"">&u64" F 10
!"FFI: Pointer element type not implemented" % f@•FFI"""bqn_init"">**u64" F 2
# pointer objects
%DEF mm %USE defs Alloc {1𝕩 {𝕏𝕨} @•FFI"*"𝕨, "calloc", size_t, size_t} free @•FFI"""free"">*"
%DEF WallocE Cpy +´(28×8)×256|(@•FFI"*:i8""memcpy""*""*""u64"){𝔽} {%USE mm allocs Clean{Free¨allocs𝕩} Clean 𝕏{𝕊: !•CurrentError Clean @} {{r allocs r 𝕨 Alloc 𝕩}}}
%DEF Walloc Cpy +´(28×8)×256|(@•FFI"*:i8""memcpy""*""*""u64"){𝔽} {%USE mm allocs Clean{Free¨allocs𝕩} Clean 𝕏 {{r allocs r 𝕨 Alloc 𝕩}}}
# .Field
%USE Walloc {{𝕊al: 1("{i32,i32,i32}" Al 99).Field0¨ ¯2+8}} %% 00111000
%USE Walloc {{𝕊al: 1("[5]u8" Al 99).Field0¨ ¯2+9}} %% 001111100
%USE Walloc {{𝕊al: 1("[5]u8" Al 99).Field0¨ ,¯∞,0÷0,@,"foo",{}}} %% 60
# .Write, .Read
%USE Walloc {{𝕊al: p"{i16,i16,i16,i64}" Al 99 p.Write ¯410000¯300007e12 s-{Cpy 0˜˜𝕩}´ p.Field 2, p Cpy p.Add 1, p, s p.Read¨ 2}} %% ¯410000¯300007e12, ¯41000000
%USE Walloc {{𝕊al: p"{i32,{i64,i64}}" Al 999 {𝕩 p.Write 𝕩×10,𝕩×2030}¨ 4 ((p.Field 1).Field 0).Read¨ 4 }} %% 20×4
!"Cannot get a field of a pointer to a scalar" % %USE WallocE {{𝕊al: ("i32" Al 99).Field 0}}
# garbage arguments
!"Expected integer, got character" % %USE WallocE {{𝕊al: p"i8" Al 1 p.Add '!'}}
!"(pointer).Sub: Unexpected argument type: character" % %USE WallocE {{𝕊al: p"i8" Al 1 p.Sub '!'}}
!"Expected non-negative integer, got character" % %USE WallocE {{𝕊al: p"i8" Al 1 p.Field '!'}}
!"Type parser: Pointer type must be a string" % %USE WallocE {{𝕊al: p"i8" Al 1 p.Cast '!'}}
!"Expected integer, got character" % %USE WallocE {{𝕊al: p"i8" Al 1 p.Read '!'}}
!"FFI: improper value for i8" % %USE WallocE {{𝕊al: p"i8" Al 1 p.Write '!'}}
# untyped pointers
!"Cannot get a field of a pointer to a scalar" % %USE WallocE {{𝕊al: ("" Al 99).Field 0}}
# %USE Walloc {{𝕊al: p←"i32" Al 99 ⋄ p.Write 123 ⋄ (((p.Cast "").Add 0).Cast"i32").Read 0}} %% 123
!"Cannot offset an untyped pointer" % %USE WallocE {{𝕊al: ("" Al 99).Add 0}}
!"Cannot offset an untyped pointer" % %USE WallocE {{𝕊al: ("" Al 99).Add 1}}
# .Add, .Sub, .Cast
%USE Walloc {{𝕊al: p"{i32,*}" Al 1 p.Sub p.Cast "{i32,*i32}"}} %% 0
%USE Walloc {{𝕊al: p"{i32,*}" Al 1 p.Sub p.Add 123}} %% ¯123
%USE Walloc {{𝕊al: p"{i32,*}" Al 1 p.Sub p.Sub 123}} %% 123
# ptr1.Sub ptr2
!"(pointer).Sub ptr: Both pointers must be typed" % %USE WallocE {{𝕊al: p"" Al 1 p.Sub p}}
!"(pointer).Sub ptr: Both pointers must be typed" % %USE WallocE {{𝕊al: p"i8" Al 1 (p.Cast "").Sub p.Cast "{{i8,i16},i32}"}}
!"(pointer).Sub ptr: Both pointers must be typed" % %USE WallocE {{𝕊al: p"i8" Al 1 (p.Cast "{{i8,i16},i32}").Sub p.Cast ""}}
!"(pointer).Sub ptr: Arguments must have the same stride" % %USE WallocE {{𝕊al: p"i8" Al 1 ((p.Cast "{{i8,i16},i32}").Field 0).Sub p.Cast "{i8,i16}"}}
!"(pointer).Sub ptr: Arguments must have compatible types" % %USE WallocE {{𝕊al: p"i8" Al 1 p.Sub p.Cast "u8"}}
!"(pointer).Sub ptr: Distance between pointers isn't an exact multiple of stride" % %USE WallocE {{𝕊al: p"i8" Al 1 (p.Cast "i32").Sub (p.Add 6).Cast "i32"}}
!"Type parser: Structs currently cannot contain mutable references" % @•FFI """bqn_init""{&i8}"
# !"" % %USE Walloc {{𝕊al: p←"i8" Al 1 ⋄ (p.Cast "{{i8,i16},i32}").Sub p.Cast "{{u8,i16},i32}"}}
# !"" % %USE Walloc {{𝕊al: p←"i8" Al 1 ⋄ (p.Cast "{{i8,*i16},i32}").Sub p.Cast "{{u8,*u16},i32}"}}
# type comparison
%USE Walloc {{𝕊al: p"i8" Al 1 t"{{i8,i16,**i8,[12]i8,*:i32,i64:f64,*,*f64},i32,i64:c8}" (p.Cast t).Sub p.Cast t}} %% 0 # ⎊-less test of most passing things to run under heapverify
%DEF TyEq {exp𝕊ab: %USE Walloc {{𝕊al: p"i8" Al 1 ! (exp990) ((p.Cast a).Sub)99 p.Cast b}}}
1 %USE TyEq "{*i16}", "{*i16}"
0 %USE TyEq "{*i16}", "{*u16}"
1 %USE TyEq "{*i16}", "{*}"
1 %USE TyEq "{*}", "{*i16}"
1 %USE TyEq "{*:i8}", "{*i16}"
1 %USE TyEq "{*:i8}", "{*i16:i8}"
1 %USE TyEq "{*:i8}", "{*i16:i32}"
1 %USE TyEq "{{i8,i16},i32}", "{{i8,i16},i32}"
0 %USE TyEq "{{i8,i16},i32}", "{{u8,i16},i32}"
1 %USE TyEq "{[3]i32,[5]i32}", "{[3]i32,[5]i32}"
1 %USE TyEq "{[3]i32,[5]i32}", "{[3]i32,[5]i32:i8}"
0 %USE TyEq "{[3]i32,[5]i32}", "{[3]i32,[5]u32}"
0 %USE TyEq "{[3]i32,[5]i32}", "{[5]i32,[3]i32}"
0 %USE TyEq "[4]i32", "[3]i32"
0 %USE TyEq "*[4]i32", "*[3]i32"
0 %USE TyEq "{i32}", "i32"
0 %USE TyEq "i16", "i32"
0 %USE TyEq "i16", "u16"
1 %USE TyEq "{i32:i8,i64}", "{i32:i8,i64}"
0 %USE TyEq "{i32:i8,i64}", "{u32:i8,i64}"
0 %USE TyEq "{i32:i8,i64}", "{i16:i8,i64}"
0 %USE TyEq "*{i32:i8}", "*{i16:i8}"
1 %USE TyEq "{i32:i8,i64}", "{i32:i16,i64}"
1 %USE TyEq "{i32:i32,i64}","{i32:u1,i64}"
1 %USE TyEq "{i32:i8,i64}", "{i32,i64}"
1 %USE TyEq "*i32:i8", "*"
1 %USE TyEq "*i32:i8", "*:c32"
# !"FFI: Unimplemented result type" % @•FFI"*i32"‿"bqn_init"
# !"FFI: Unimplemented result type" % @•FFI"&i32"‿"bqn_init"
# unchecked stuff
# !"FFI: Bad array corresponding to ""i64:c8"": expected 8 elements, got 1" % f←@•FFI""‿"bqn_init"‿">i64:c8" ⋄ F 8⥊2