Skip to content

Commit bd12523

Browse files
Merge pull request #144 from StartAutomating/PipeScriptKeywordsAndRestfulImprovements
Pipe script keywords and restful improvements
2 parents bb43b26 + 5775e15 commit bd12523

File tree

12 files changed

+378
-30
lines changed

12 files changed

+378
-30
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
## 0.0.12:
2+
* Adding assert keyword (#143)
3+
* Fixing new keyword for blank constructors (#142 )
4+
* Rest Transpiler:
5+
* Handling multiple QueryString values (#139)
6+
* Only passing ContentType to invoker if invoker supports it (#141)
7+
* Defaulting to JSON body when ContentType is unspecified (#140)
8+
---
9+
110
## 0.0.11:
211
* Source Generators Now Support Parameters / Arguments (#75)
312
* Invoke-PipeScript Terminating Build Errors (#135)

PipeScript.psd1

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,33 @@
11
@{
2-
ModuleVersion = '0.0.11'
2+
ModuleVersion = '0.0.12'
33
Description = 'An Extensible Transpiler for PowerShell (and anything else)'
44
RootModule = 'PipeScript.psm1'
55
PowerShellVersion = '4.0'
66
AliasesToExport = '*'
77
FormatsToProcess = 'PipeScript.format.ps1xml'
88
TypesToProcess = 'PipeScript.types.ps1xml'
9-
Guid = 'fc054786-b1ce-4ed8-a90f-7cc9c27edb06'
10-
CompanyName='Start-Automating'
11-
Copyright='2022 Start-Automating'
12-
Author='James Brundage'
9+
Guid = 'fc054786-b1ce-4ed8-a90f-7cc9c27edb06'
10+
CompanyName = 'Start-Automating'
11+
Copyright = '2022 Start-Automating'
12+
Author = 'James Brundage'
1313
PrivateData = @{
1414
PSData = @{
1515
ProjectURI = 'https://github.com/StartAutomating/PipeScript'
1616
LicenseURI = 'https://github.com/StartAutomating/PipeScript/blob/main/LICENSE'
17-
18-
Tags = 'PipeScript','PowerShell', 'Transpilation', 'Compiler'
17+
RecommendModule = @('PSMinifier')
18+
RelatedModule = @()
19+
BuildModule = @('EZOut','Piecemeal','PipeScript','HelpOut', 'PSDevOps')
20+
Tags = 'PipeScript','PowerShell', 'Transpilation', 'Compiler'
1921
ReleaseNotes = @'
22+
## 0.0.12:
23+
* Adding assert keyword (#143)
24+
* Fixing new keyword for blank constructors (#142 )
25+
* Rest Transpiler:
26+
* Handling multiple QueryString values (#139)
27+
* Only passing ContentType to invoker if invoker supports it (#141)
28+
* Defaulting to JSON body when ContentType is unspecified (#140)
29+
---
30+
2031
## 0.0.11:
2132
* Source Generators Now Support Parameters / Arguments (#75)
2233
* Invoke-PipeScript Terminating Build Errors (#135)

README.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,16 @@
44

55
# What Is PipeScript?
66

7-
> PipeScript is a transpiled scripting language built atop of PowerShell.
7+
PipeScript is a scripting language built atop PowerShell.
88

9-
> PipeScript can be run interactively
109

11-
> PipeScript can embedded within many languages to dynamically generate source code
10+
PipeScript is transpiled into PowerShell.
11+
12+
13+
PipeScript can be run interactively, or used to build more PowerShell with less code.
14+
15+
16+
PipeScript can also be embedded in many other languages to dynamically generate source code.
1217

1318
## What's a Transpiler?
1419

Transpilers/Keywords/Assert.psx.ps1

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
<#
2+
.SYNOPSIS
3+
Assert keyword
4+
.DESCRIPTION
5+
Assert is a common keyword in many programming languages.
6+
7+
In PipeScript, Asset will take a condition and an optional action.
8+
9+
The condtion may be contained in either parenthesis or a [ScriptBlock].
10+
11+
If there is no action, the assertion will throw an exception containing the condition.
12+
13+
If the action is a string, the assertion will throw that error as a string.
14+
15+
If the action is a ScriptBlock, it will be run if the assertion is false.
16+
17+
Assertions will not be transpiled or included if -Verbose or -Debug has not been set.
18+
19+
Additionally, while running, Assertions will be ignored if -Verbose or -Debug has not been set.
20+
.EXAMPLE
21+
# With no second argument, assert will throw an error with the condition of the assertion.
22+
Invoke-PipeScript {
23+
assert (1 -eq 1)
24+
} -Debug
25+
.EXAMPLE
26+
# With a second argument of a string, assert will throw an error
27+
Invoke-PipeScript {
28+
assert ($true) "It's true"
29+
} -Debug
30+
.EXAMPLE
31+
# Conditions can also be written as a ScriptBlock
32+
Invoke-PipeScript {
33+
assert {$true} "Process id '$pid' Asserted"
34+
} -Verbose
35+
.EXAMPLE
36+
# If the assertion action was a ScriptBlock, no exception is automatically thrown
37+
Invoke-PipeScript {
38+
assert ($true) { Write-Information "Assertion was true"}
39+
} -Verbose
40+
#>
41+
[ValidateScript({
42+
# This transpiler should run if the command is literally 'assert'
43+
$commandAst = $_
44+
return ($commandAst -and $CommandAst.CommandElements[0].Value -eq 'assert')
45+
})]
46+
param(
47+
# The CommandAst
48+
[Parameter(Mandatory,ValueFromPipeline,ParameterSetName='CommandAst')]
49+
[Management.Automation.Language.CommandAst]
50+
$CommandAst
51+
)
52+
53+
process {
54+
$CommandName, $CommandArgs = $commandAst.CommandElements
55+
$firstArg, $secondArg = $CommandArgs
56+
57+
# If the first arg can be a condition in simple or complex form
58+
if (-not $firstArg -or $firstArg.GetType().Name -notin
59+
'ParenExpressionAst',
60+
'ScriptBlockExpressionAst',
61+
'VariableExpressionAst',
62+
'MemberExpressionAst',
63+
'StringConstantExpressionAst',
64+
'ExpandableStringExpressionAst') {
65+
# If it was the wrong type, let them know.
66+
Write-Error "Assert must be followed by one of the following expressions:
67+
* Variable
68+
* Member
69+
* String
70+
* Parenthesis
71+
* ScriptBlock
72+
"
73+
return
74+
}
75+
76+
# If there was a second argument, it must be a string or ScriptBlock.
77+
if ($secondArg -and $secondArg.GetType().Name -notin
78+
'ScriptBlockExpressionAst',
79+
'StringConstantExpressionAst',
80+
'ExpandableStringExpressionAst') {
81+
Write-Error "Assert must be followed by a ScriptBlock or string"
82+
return
83+
}
84+
85+
# We need to create a [ScriptBlock] for the condition so we can transpile it.
86+
$firstArgTypeName = $firstArg.GetType().Name
87+
# The condition will always check for -DebugPreference or -VerbosePreference.
88+
$checkDebugPreference = '($debugPreference,$verbosePreference -ne ''silentlyContinue'')'
89+
90+
$condition =
91+
[ScriptBlock]::Create("($checkDebugPreference -and $(
92+
# If the condition is already in parenthesis,
93+
if ($firstArgTypeName -eq 'ParenExpressionAst') {
94+
"$FirstArg" # leave it alone.
95+
}
96+
# If the condition is a ScriptBlockExpression,
97+
elseif ($firstArgTypeName -eq 'ScriptBlockExpressionAst')
98+
{
99+
# put it in parenthesis.
100+
"($($FirstArg -replace '^\{' -replace '\}$'))"
101+
}
102+
# Otherwise
103+
else
104+
{
105+
"($FirstArg)" # embed the condition in parenthesis.
106+
}
107+
))")
108+
109+
# Transpile the condition.
110+
$condition = $condition | .>Pipescript
111+
112+
# Now we create the entire assertion script
113+
$newScript =
114+
# If there was no second argument
115+
if (-not $secondArg) {
116+
# Rethrow the condition
117+
"if $condition { throw '{$($firstArg -replace "'", "''")}' } "
118+
} elseif ($secondArg.GetType().Name -eq 'ScriptBlockExpressionAst') {
119+
# If the second argument was a script, transpile and embed it.
120+
"if $condition {$([ScriptBlock]::Create(
121+
($secondArg -replace '^\{' -replace '\}$')
122+
) | .>Pipescript)}"
123+
} else {
124+
# Otherwise, throw the second argument.
125+
"if $condition { throw $secondArg } "
126+
}
127+
128+
if ($DebugPreference, $VerbosePreference -ne 'silentlyContinue') {
129+
[scriptblock]::Create($newScript)
130+
} else {
131+
{}
132+
}
133+
}

Transpilers/Keywords/New.psx.ps1

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
.> { new byte 1 }
2020
.EXAMPLE
2121
.> { new int[] 5 }
22+
.EXAMPLE
23+
.> { new Timespan }
2224
.EXAMPLE
2325
.> { new datetime 12/31/1999 }
2426
.EXAMPLE
@@ -97,7 +99,13 @@ process {
9799
$constructorArguments[0] -is [string]) {
98100
"[$newTypeName]::parse(" + ($constructorArguments -join ',') + ")"
99101
} elseif ($realNewType::new) {
100-
"[$newTypeName]::new(" + ($constructorArguments -join ',') + ")"
102+
if ($constructorArguments) {
103+
"[$newTypeName]::new(" + ($constructorArguments -join ',') + ")"
104+
} elseif ($realNewType::new.overloadDefinitions -notmatch '\(\)$') {
105+
"[$newTypeName]::new(`$null)"
106+
} else {
107+
"[$newTypeName]::new()"
108+
}
101109
} elseif ($realNewType.IsPrimitive) {
102110
if ($constructorArguments) {
103111
if ($constructorArguments.Length -eq 1) {

Transpilers/Keywords/README.md

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,54 @@ This directory and it's subdirectories contain additional language keywords with
33
Most keywords will be implemented as a Transpiler that tranforms a CommandAST.
44

55

6-
|DisplayName |Synopsis |
7-
|------------------|----------------------------|
8-
|[New](New.psx.ps1)|['new' keyword](New.psx.ps1)|
6+
|DisplayName |Synopsis |
7+
|------------------------|--------------------------------|
8+
|[Assert](Assert.psx.ps1)|[Assert keyword](Assert.psx.ps1)|
9+
|[New](New.psx.ps1) |['new' keyword](New.psx.ps1) |
910

1011

1112

1213

14+
## Assert Example 1
15+
16+
17+
~~~PowerShell
18+
# With no second argument, assert will throw an error with the condition of the assertion.
19+
Invoke-PipeScript {
20+
assert (1 -eq 1)
21+
} -Debug
22+
~~~
23+
24+
## Assert Example 2
25+
26+
27+
~~~PowerShell
28+
# With a second argument of a string, assert will throw an error
29+
Invoke-PipeScript {
30+
assert ($true) "It's true"
31+
} -Debug
32+
~~~
33+
34+
## Assert Example 3
35+
36+
37+
~~~PowerShell
38+
# Conditions can also be written as a ScriptBlock
39+
Invoke-PipeScript {
40+
assert {$true} "Process id '$pid' Asserted"
41+
} -Verbose
42+
~~~
43+
44+
## Assert Example 4
45+
46+
47+
~~~PowerShell
48+
# If the assertion action was a ScriptBlock, no exception is automatically thrown
49+
Invoke-PipeScript {
50+
assert ($true) { Write-Information "Assertion was true"}
51+
} -Verbose
52+
~~~
53+
1354
## New Example 1
1455

1556

@@ -35,19 +76,26 @@ Most keywords will be implemented as a Transpiler that tranforms a CommandAST.
3576

3677

3778
~~~PowerShell
38-
.> { new datetime 12/31/1999 }
79+
.> { new Timespan }
3980
~~~
4081

4182
## New Example 5
4283

4384

4485
~~~PowerShell
45-
.> { new @{RandomNumber = Get-Random; A ='b'}}
86+
.> { new datetime 12/31/1999 }
4687
~~~
4788

4889
## New Example 6
4990

5091

92+
~~~PowerShell
93+
.> { new @{RandomNumber = Get-Random; A ='b'}}
94+
~~~
95+
96+
## New Example 7
97+
98+
5199
~~~PowerShell
52100
.> { new Diagnostics.ProcessStartInfo @{FileName='f'} }
53101
~~~

0 commit comments

Comments
 (0)