This repository was archived by the owner on Aug 31, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 227
Expand file tree
/
Copy pathassert.lcb
More file actions
144 lines (116 loc) · 4.53 KB
/
assert.lcb
File metadata and controls
144 lines (116 loc) · 4.53 KB
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
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
89
90
91
92
93
94
95
96
97
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
/*
Copyright (C) 2016 LiveCode Ltd.
This file is part of LiveCode.
LiveCode is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License v3 as published by the Free
Software Foundation.
LiveCode is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with LiveCode. If not see <http://www.gnu.org/licenses/>. */
/**
Sometimes there are restrictions about how some LCB code can be used
correctly. It may only be possible to make it work in a sensible way
if is passed a particular range of values, or if the system is in a
particular state. These are known as "preconditions" for the code.
Many preconditions can be expressed via the LCB type system. For
example, you can declare that the parameters passed to handler must be
particular types of value. For example, when you write `in pName as
String`, you are saying that the handler can only work when the
`pName` parameter is a character string. This is a precondition that
can be checked automatically by the LCB compiler and virtual machine.
Some preconditions can't yet be automatically checked by LCB. An
example would be a requirement that a string contains only ASCII
characters, or that an array has a particular key.
This module provides syntax to assist with explicit precondition
checks.
*/
module com.livecode.assert
/**
Summary: Check a precondition
Parameters:
Condition: Expression that must be true for code to work
Example:
handler BoxValue(in pValue as any) returns Array
return { "__VALUE": pValue }
end handler
handler UnBoxValue(in pBox as Array) returns any
expect that "__VALUE" is among the elements of pBox
return pBox["__VALUE"]
end handler
Description:
Use this statement at the start of a handler to check that necessary
preconditions for the handler are satisfied. For example, the handler
may require that its parameters have a particular structure or fall
within a particular range, or may need the system to be in a specific
state.
Note that if the <Condition> is false, this statement will throw an
error with the slightly-unhelpful message that "assertion failed".
Usually, it will be more useful to use <ExpectsPreconditionWithReason>
instead.
Related: ExpectPreconditionWithReason(statement).
Tags: Assertions
*/
syntax ExpectPrecondition is statement
"expect" ["that"] <Condition: Expression>
begin
MCAssertExpectPrecondition(Condition)
end syntax
public handler MCAssertExpectPrecondition(in pCondition as Boolean) \
returns nothing
if pCondition then
return
end if
throw "assertion failed"
end handler
/**
Summary: Check a precondition, with a reason
Parameters:
Condition: Expression that must be true for code to work
Reason: Description of the precondition
Example:
-- Draw a random variate from the Bernoulli distribution with
-- parameter pParam. A Bernoulli variate may be 0 or 1; the
-- parameter pParam is the probability that the result is 1.
handler BernoulliVariate(in pParam as Number) returns Number
expect (pParam >= 0 and pParam <= 1) \
because "Bernoulli parameter must be a probability in [0,1]"
if (any number <= pParam) then
return 1
else
return 0
end if
end handler
Description:
Use this statement at the start of a handler to check that necessary
preconditions for the handler are satisfied. For example, the handler
may require that its parameters have a particular structure or fall
within a particular range, or may need the system to be in a specific
state.
If the <Condition> is false, an error will be thrown including the
<Reason> for the check.
Related: ExpectPrecondition (statement)
Tags: Assertions
*/
syntax ExpectPreconditionWithReason is statement
"expect" ["that"] <Condition: Expression> "because" <Reason: Expression>
begin
MCAssertExpectPreconditionWithReason(Condition, Reason)
end syntax
-- Bind to the single string operation that this module needs here,
-- rather than messing about with a separate implementation module.
public foreign handler MCStringExecPutStringBefore(in Source as String, \
inout Target as String) returns nothing binds to "<builtin>"
public handler MCAssertExpectPreconditionWithReason \
(in pCondition as Boolean, in pReason as String) returns nothing
if pCondition then
return
end if
unsafe
MCStringExecPutStringBefore("assertion failed: ", pReason)
end unsafe
throw pReason
end handler
end module