functionalscript 0.0.352 → 0.0.355
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/com/cs/main.f.js +112 -0
- package/com/cs/test/Program.cs +2 -0
- package/com/cs/test/build.js +11 -0
- package/com/cs/test/test.csproj +11 -0
- package/com/cs/test.f.js +63 -0
- package/com/main.f.js +5 -29
- package/com/types/main.f.js +55 -0
- package/package.json +1 -1
- package/test.f.js +1 -0
- package/text/main.f.js +17 -11
- package/text/test.f.js +7 -6
- package/types/list/main.f.js +6 -2
- package/types/list/test.f.js +10 -0
- package/com/test.f.js +0 -23
package/com/cs/main.f.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
const types = require('../types/main.f.js')
|
|
2
|
+
const text = require('../../text/main.f.js')
|
|
3
|
+
const list = require('../../types/list/main.f.js')
|
|
4
|
+
const obj = require('../../types/object/main.f.js')
|
|
5
|
+
|
|
6
|
+
/** @type {(v: string) => string} */
|
|
7
|
+
const csUsing = v => `using ${v};`
|
|
8
|
+
|
|
9
|
+
/** @type {(type: string) => (name: string) => (body: text.Block) => text.Block} */
|
|
10
|
+
const csBlock = type => name => body => [`${type} ${name}`, '{', body, '}']
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @type {(attributes: list.List<string>) =>
|
|
14
|
+
* (type: string) =>
|
|
15
|
+
* (name: string) =>
|
|
16
|
+
* (body: text.Block) =>
|
|
17
|
+
* list.List<text.Item>}
|
|
18
|
+
*/
|
|
19
|
+
const csTypeDef = attributes => type => name => body =>
|
|
20
|
+
list.flat([
|
|
21
|
+
list.map(v => `[${v}]`)(attributes),
|
|
22
|
+
csBlock(`public ${type}`)(name)(body)
|
|
23
|
+
])
|
|
24
|
+
|
|
25
|
+
/** @type {(t: types.BaseType) => string} */
|
|
26
|
+
const csBaseType = t => {
|
|
27
|
+
switch (t) {
|
|
28
|
+
case 'bool': return 'bool'
|
|
29
|
+
case 'f32': return 'float'
|
|
30
|
+
case 'f64': return 'double'
|
|
31
|
+
case 'i16': return 'short'
|
|
32
|
+
case 'i32': return 'int'
|
|
33
|
+
case 'i64': return 'long'
|
|
34
|
+
case 'i8': return 'sbyte'
|
|
35
|
+
case 'isize': return 'IntPtr'
|
|
36
|
+
case 'u16': return 'ushort'
|
|
37
|
+
case 'u32': return 'uint'
|
|
38
|
+
case 'u64': return 'ulong'
|
|
39
|
+
case 'u8': return 'byte'
|
|
40
|
+
case 'usize': return 'UIntPtr'
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** @type {(isUnsafe: boolean) => string} */
|
|
45
|
+
const unsafe = isUnsafe => isUnsafe ? 'unsafe ' : ''
|
|
46
|
+
|
|
47
|
+
/** @type {(t: types.Type) => readonly[boolean, string]} */
|
|
48
|
+
const csType = t =>
|
|
49
|
+
typeof (t) === 'string' ? [false, csBaseType(t)] :
|
|
50
|
+
t instanceof Array ? [false, t[0]] :
|
|
51
|
+
[true, `${csType(t['*'])[1]}*`]
|
|
52
|
+
|
|
53
|
+
/** @type {(f: types.Field) => string} */
|
|
54
|
+
const csParam = ([name, type]) => `${csType(type)[1]} ${name}`
|
|
55
|
+
|
|
56
|
+
/** @type {(f: types.Field) => string} */
|
|
57
|
+
const csField = ([name, type]) => {
|
|
58
|
+
const [isUnsafe, t] = csType(type)
|
|
59
|
+
return `public ${unsafe(isUnsafe)}${t} ${name};`
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** @type {(m: types.Method) => readonly[boolean, string]} */
|
|
63
|
+
const csResult = m => m.length === 2 ? [false, 'void'] : csType(m[2])
|
|
64
|
+
|
|
65
|
+
/** @type {(field: types.Field) => boolean} */
|
|
66
|
+
const isUnsafeField = field => csType(field[1])[0]
|
|
67
|
+
|
|
68
|
+
/** @type {(m: types.Method) => readonly string[]} */
|
|
69
|
+
const csMethod = m => {
|
|
70
|
+
const result = csResult(m)
|
|
71
|
+
const isUnsafe = result[0] || list.some(list.map(isUnsafeField)(m[1]))
|
|
72
|
+
return [
|
|
73
|
+
'[PreserveSig]',
|
|
74
|
+
`${unsafe(isUnsafe)}${result[1]} ${m[0]}(${list.join(', ')(list.map(csParam)(m[1]))});`
|
|
75
|
+
]
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** @type {(e: obj.Entry<types.Definition>) => list.List<text.Item>} */
|
|
79
|
+
const csDef = ([n, d]) => {
|
|
80
|
+
const i = d.interface
|
|
81
|
+
return i === undefined ?
|
|
82
|
+
csTypeDef
|
|
83
|
+
(['StructLayout(LayoutKind.Sequential)'])
|
|
84
|
+
('struct')
|
|
85
|
+
(n)
|
|
86
|
+
(() => list.map(csField)(d.struct)) :
|
|
87
|
+
csTypeDef
|
|
88
|
+
([`Guid("${d.guid}")`, 'InterfaceType(ComInterfaceType.InterfaceIsIUnknown)'])
|
|
89
|
+
('interface')
|
|
90
|
+
(n)
|
|
91
|
+
(() => list.flatMap(csMethod)(d.interface))
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** @type {(name: string) => (library: types.Library) => text.Block} */
|
|
95
|
+
const cs = name => library => {
|
|
96
|
+
const v = list.flatMap(csDef)(Object.entries(library))
|
|
97
|
+
|
|
98
|
+
/** @type {text.Block} */
|
|
99
|
+
const h = [
|
|
100
|
+
csUsing('System'),
|
|
101
|
+
csUsing('System.Runtime.InteropServices'),
|
|
102
|
+
''
|
|
103
|
+
]
|
|
104
|
+
|
|
105
|
+
const ns = csBlock('namespace')(name)(() => v)
|
|
106
|
+
return () => list.flat([h, ns])
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
module.exports = {
|
|
110
|
+
/** @readonly */
|
|
111
|
+
cs,
|
|
112
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const fs = require('node:fs')
|
|
2
|
+
const cp = require('node:child_process')
|
|
3
|
+
const cs = require('../test.f.js').result
|
|
4
|
+
|
|
5
|
+
fs.writeFileSync('_result.cs', cs)
|
|
6
|
+
try {
|
|
7
|
+
console.log(cp.execSync('dotnet build').toString())
|
|
8
|
+
} catch (e) {
|
|
9
|
+
// @ts-ignore
|
|
10
|
+
console.log(e.output.toString())
|
|
11
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<Project Sdk="Microsoft.NET.Sdk">
|
|
2
|
+
|
|
3
|
+
<PropertyGroup>
|
|
4
|
+
<OutputType>Exe</OutputType>
|
|
5
|
+
<TargetFramework>net6.0</TargetFramework>
|
|
6
|
+
<ImplicitUsings>enable</ImplicitUsings>
|
|
7
|
+
<Nullable>enable</Nullable>
|
|
8
|
+
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
|
9
|
+
</PropertyGroup>
|
|
10
|
+
|
|
11
|
+
</Project>
|
package/com/cs/test.f.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
const types = require('../types/main.f.js')
|
|
2
|
+
const _ = require('./main.f.js')
|
|
3
|
+
const list = require('../../types/list/main.f.js')
|
|
4
|
+
const text = require('../../text/main.f.js')
|
|
5
|
+
|
|
6
|
+
/** @type {types.Library} */
|
|
7
|
+
const library = {
|
|
8
|
+
Slice: {
|
|
9
|
+
struct: [
|
|
10
|
+
['Start', { '*': 'u8' }],
|
|
11
|
+
['Size', 'usize'],
|
|
12
|
+
]
|
|
13
|
+
},
|
|
14
|
+
IMy: {
|
|
15
|
+
guid: 'C66FB270-2D80-49AD-BB6E-88C1F90B805D',
|
|
16
|
+
interface: [
|
|
17
|
+
['GetSlice', [], ['Slice']],
|
|
18
|
+
['SetSlice', [['slice', ['Slice']]]],
|
|
19
|
+
['GetUnsafe', [], {'*': 'bool'}],
|
|
20
|
+
['SetUnsafe', [['p', {'*': ['Slice']}], ['size', 'u32']]],
|
|
21
|
+
],
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const f = () =>
|
|
26
|
+
{
|
|
27
|
+
const cs = list.join('\n')(text.flat(' ')(_.cs('My')(library)))
|
|
28
|
+
const e =
|
|
29
|
+
'using System;\n' +
|
|
30
|
+
'using System.Runtime.InteropServices;\n' +
|
|
31
|
+
'\n' +
|
|
32
|
+
'namespace My\n' +
|
|
33
|
+
'{\n' +
|
|
34
|
+
' [StructLayout(LayoutKind.Sequential)]\n' +
|
|
35
|
+
' public struct Slice\n' +
|
|
36
|
+
' {\n' +
|
|
37
|
+
' public unsafe byte* Start;\n' +
|
|
38
|
+
' public UIntPtr Size;\n' +
|
|
39
|
+
' }\n' +
|
|
40
|
+
' [Guid("C66FB270-2D80-49AD-BB6E-88C1F90B805D")]\n' +
|
|
41
|
+
' [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]\n' +
|
|
42
|
+
' public interface IMy\n' +
|
|
43
|
+
' {\n' +
|
|
44
|
+
' [PreserveSig]\n' +
|
|
45
|
+
' Slice GetSlice();\n' +
|
|
46
|
+
' [PreserveSig]\n' +
|
|
47
|
+
' void SetSlice(Slice slice);\n' +
|
|
48
|
+
' [PreserveSig]\n' +
|
|
49
|
+
' unsafe bool* GetUnsafe();\n' +
|
|
50
|
+
' [PreserveSig]\n' +
|
|
51
|
+
' unsafe void SetUnsafe(Slice* p, uint size);\n' +
|
|
52
|
+
' }\n' +
|
|
53
|
+
'}'
|
|
54
|
+
if (cs !== e) { throw [cs,e] }
|
|
55
|
+
return cs
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const result = f()
|
|
59
|
+
|
|
60
|
+
module.exports = {
|
|
61
|
+
/** @readonly */
|
|
62
|
+
result,
|
|
63
|
+
}
|
package/com/main.f.js
CHANGED
|
@@ -1,30 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
const types = require('./types/main.f.js');
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
/** @typedef {readonly Field[]} FieldArray */
|
|
8
|
-
|
|
9
|
-
/** @typedef {[string, Type]} Field */
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* @typedef {{
|
|
13
|
-
* readonly interface: MethodArray
|
|
14
|
-
* readonly guid: string
|
|
15
|
-
* }} Interface
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
/** @typedef {readonly Method[]} MethodArray */
|
|
19
|
-
|
|
20
|
-
/** @typedef {readonly[string, FieldArray, Type]} Method */
|
|
21
|
-
|
|
22
|
-
/** @typedef {BaseType|Id|Pointer} Type */
|
|
23
|
-
|
|
24
|
-
/** @typedef {readonly[string]} Id */
|
|
25
|
-
|
|
26
|
-
/** @typedef {'u8'|'i8'|'u16'|'i16'|'u32'|'i32'|'u64'|'i64'|'usize'|'isize'|'f32'|'f64'|'bool'|''} BaseType */
|
|
27
|
-
|
|
28
|
-
/** @typedef {{readonly '*': Type}} Pointer */
|
|
29
|
-
|
|
30
|
-
module.exports = {}
|
|
3
|
+
module.exports = {
|
|
4
|
+
/** @readonly */
|
|
5
|
+
types,
|
|
6
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/** @typedef {{readonly[k in string]: Definition}} Library */
|
|
2
|
+
|
|
3
|
+
/** @typedef {Struct|Interface} Definition */
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @typedef {{
|
|
7
|
+
* readonly interface?: undefined
|
|
8
|
+
* readonly struct: FieldArray
|
|
9
|
+
* }} Struct
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/** @typedef {readonly Field[]} FieldArray */
|
|
13
|
+
|
|
14
|
+
/** @typedef {readonly[string, Type]} Field */
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @typedef {{
|
|
18
|
+
* readonly interface: MethodArray
|
|
19
|
+
* readonly guid: string
|
|
20
|
+
* }} Interface
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/** @typedef {readonly Method[]} MethodArray */
|
|
24
|
+
|
|
25
|
+
/** @typedef {readonly[string, FieldArray, Type]} GetMethod */
|
|
26
|
+
|
|
27
|
+
/** @typedef {readonly[string, FieldArray]} SetMethod */
|
|
28
|
+
|
|
29
|
+
/** @typedef {GetMethod|SetMethod} Method */
|
|
30
|
+
|
|
31
|
+
/** @typedef {BaseType|Id|Pointer} Type */
|
|
32
|
+
|
|
33
|
+
/** @typedef {readonly[string]} Id */
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @typedef {|
|
|
37
|
+
* 'u8'|
|
|
38
|
+
* 'i8'|
|
|
39
|
+
* 'u16'|
|
|
40
|
+
* 'i16'|
|
|
41
|
+
* 'u32'|
|
|
42
|
+
* 'i32'|
|
|
43
|
+
* 'u64'|
|
|
44
|
+
* 'i64'|
|
|
45
|
+
* 'usize'|
|
|
46
|
+
* 'isize'|
|
|
47
|
+
* 'f32'|
|
|
48
|
+
* 'f64'|
|
|
49
|
+
* 'bool'
|
|
50
|
+
* } BaseType
|
|
51
|
+
*/
|
|
52
|
+
|
|
53
|
+
/** @typedef {{readonly '*': Type}} Pointer */
|
|
54
|
+
|
|
55
|
+
module.exports = {}
|
package/package.json
CHANGED
package/test.f.js
CHANGED
package/text/main.f.js
CHANGED
|
@@ -1,21 +1,27 @@
|
|
|
1
1
|
const list = require('../types/list/main.f.js')
|
|
2
2
|
|
|
3
|
-
/** @typedef {
|
|
3
|
+
/** @typedef {ItemThunk|ItemArray} Block */
|
|
4
4
|
|
|
5
|
-
/** @typedef {
|
|
5
|
+
/** @typedef {readonly Item[]} ItemArray */
|
|
6
6
|
|
|
7
|
-
/** @
|
|
7
|
+
/** @typedef {() => list.List<Item>} ItemThunk */
|
|
8
|
+
|
|
9
|
+
/** @typedef {string|ItemArray|ItemThunk} Item */
|
|
10
|
+
|
|
11
|
+
/** @type {(indent: string) => (text: Block) => list.List<string>} */
|
|
8
12
|
const flat = indent => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
|
|
14
|
+
/** @type {(prefix: string) => (text: Block) => list.List<string>} */
|
|
15
|
+
const f = prefix => {
|
|
16
|
+
/** @type {(item: Item) => list.List<string>} */
|
|
17
|
+
const g = item => typeof (item) === 'string' ? [`${prefix}${item}`] : f(`${prefix}${indent}`)(item)
|
|
18
|
+
return list.flatMap(g)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return f('')
|
|
16
22
|
}
|
|
17
23
|
|
|
18
24
|
module.exports = {
|
|
19
25
|
/** @readonly */
|
|
20
26
|
flat,
|
|
21
|
-
}
|
|
27
|
+
}
|
package/text/test.f.js
CHANGED
|
@@ -2,17 +2,18 @@ const _ = require('./main.f.js')
|
|
|
2
2
|
const list = require('../types/list/main.f.js')
|
|
3
3
|
|
|
4
4
|
{
|
|
5
|
-
/** @type {_.
|
|
5
|
+
/** @type {_.Block} */
|
|
6
6
|
const text = [
|
|
7
7
|
'a',
|
|
8
8
|
'b',
|
|
9
|
-
[
|
|
9
|
+
() => [
|
|
10
10
|
'c',
|
|
11
|
-
['d'],
|
|
12
|
-
]
|
|
11
|
+
() => ['d'],
|
|
12
|
+
],
|
|
13
|
+
'e',
|
|
13
14
|
]
|
|
14
|
-
const result = list.join('\n')(_.flat('
|
|
15
|
-
if (result !== 'a\nb\
|
|
15
|
+
const result = list.join('\n')(_.flat(':')(text))
|
|
16
|
+
if (result !== 'a\nb\n:c\n::d\ne') { throw result }
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
module.exports = {}
|
package/types/list/main.f.js
CHANGED
|
@@ -172,8 +172,7 @@ const drop = n => apply(dropStep(n))
|
|
|
172
172
|
/** @type {<D>(def: D) => <T>(input: List<T>) => D|T} */
|
|
173
173
|
const first = def => input => {
|
|
174
174
|
const result = next(input)
|
|
175
|
-
|
|
176
|
-
return result.first
|
|
175
|
+
return result === undefined ? def : result.first
|
|
177
176
|
}
|
|
178
177
|
|
|
179
178
|
/** @type {<D>(first: D) => <T>(tail: List<T>) => D|T} */
|
|
@@ -215,6 +214,9 @@ const countdown = count => () => {
|
|
|
215
214
|
return { first, tail: countdown(first) }
|
|
216
215
|
}
|
|
217
216
|
|
|
217
|
+
/** @type {<T>(v: T) => (c: number) => List<T>} */
|
|
218
|
+
const repeat = v => n => map(() => v)(countdown(n))
|
|
219
|
+
|
|
218
220
|
/** @type {<T>(list: List<T>) => List<T>} */
|
|
219
221
|
const cycle = list => () => {
|
|
220
222
|
const i = next(list)
|
|
@@ -355,6 +357,8 @@ module.exports = {
|
|
|
355
357
|
/** @readonly */
|
|
356
358
|
countdown,
|
|
357
359
|
/** @readonly */
|
|
360
|
+
repeat,
|
|
361
|
+
/** @readonly */
|
|
358
362
|
cycle,
|
|
359
363
|
/** @readonly */
|
|
360
364
|
scan,
|
package/types/list/test.f.js
CHANGED
|
@@ -354,6 +354,16 @@ const stress = () => {
|
|
|
354
354
|
}
|
|
355
355
|
}
|
|
356
356
|
|
|
357
|
+
{
|
|
358
|
+
const s = _.join('.')(_.repeat('x')(0))
|
|
359
|
+
if (s != '') { throw s }
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
{
|
|
363
|
+
const s = _.join('.')(_.repeat('x')(5))
|
|
364
|
+
if (s != 'x.x.x.x.x') { throw s }
|
|
365
|
+
}
|
|
366
|
+
|
|
357
367
|
// stress()
|
|
358
368
|
|
|
359
369
|
module.exports = {
|
package/com/test.f.js
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
const _ = require('./main.f.js')
|
|
2
|
-
|
|
3
|
-
/** @type {_.Library} */
|
|
4
|
-
const library = {
|
|
5
|
-
Slice: {
|
|
6
|
-
struct: [
|
|
7
|
-
['Start', { '*': 'u8' }],
|
|
8
|
-
['End', 'usize'],
|
|
9
|
-
]
|
|
10
|
-
},
|
|
11
|
-
IMy: {
|
|
12
|
-
guid: 'C66FB270-2D80-49AD-BB6E-88C1F90B805D',
|
|
13
|
-
interface: [
|
|
14
|
-
['GetSlice', [], ['Slice']],
|
|
15
|
-
['SetSlice',
|
|
16
|
-
[['slice', ['Slice']]],
|
|
17
|
-
''
|
|
18
|
-
],
|
|
19
|
-
],
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
module.exports = {}
|