mirror of
https://github.com/GayPizzaSpecifications/pork.git
synced 2025-08-03 05:10:55 +00:00
language: add boolean and/or operators, change negation syntax
This commit is contained in:
parent
0aab45094a
commit
b0fbf3ee53
@ -96,6 +96,12 @@ types:
|
||||
- name: LesserEqual
|
||||
values:
|
||||
token: "<="
|
||||
- name: BooleanAnd
|
||||
values:
|
||||
token: "and"
|
||||
- name: BooleanOr
|
||||
values:
|
||||
token: "or"
|
||||
- name: BinaryAnd
|
||||
values:
|
||||
token: "&"
|
||||
@ -196,9 +202,9 @@ types:
|
||||
- name: token
|
||||
type: String
|
||||
enums:
|
||||
- name: Negate
|
||||
- name: BooleanNot
|
||||
values:
|
||||
token: "!"
|
||||
token: "not"
|
||||
- name: UnaryPlus
|
||||
values:
|
||||
token: "+"
|
||||
|
@ -19,6 +19,8 @@ enum class InfixOperator(val token: String) {
|
||||
Greater(">"),
|
||||
GreaterEqual(">="),
|
||||
LesserEqual("<="),
|
||||
BooleanAnd("and"),
|
||||
BooleanOr("or"),
|
||||
BinaryAnd("&"),
|
||||
BinaryOr("|"),
|
||||
BinaryExclusiveOr("^")
|
||||
|
@ -7,7 +7,7 @@ import kotlinx.serialization.Serializable
|
||||
@Serializable
|
||||
@SerialName("prefixOperator")
|
||||
enum class PrefixOperator(val token: String) {
|
||||
Negate("!"),
|
||||
BooleanNot("not"),
|
||||
UnaryPlus("+"),
|
||||
UnaryMinus("-"),
|
||||
BinaryNot("~")
|
||||
|
@ -92,7 +92,7 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
||||
override fun visitPrefixOperation(node: PrefixOperation): Any {
|
||||
val value = node.expression.visit(this)
|
||||
return when (node.op) {
|
||||
PrefixOperator.Negate -> {
|
||||
PrefixOperator.BooleanNot -> {
|
||||
if (value !is Boolean) {
|
||||
throw RuntimeException("Cannot negate a value which is not a boolean.")
|
||||
}
|
||||
@ -192,6 +192,14 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
||||
else -> {}
|
||||
}
|
||||
|
||||
if (left is Boolean && right is Boolean) {
|
||||
when (node.op) {
|
||||
InfixOperator.BooleanAnd -> return left && right
|
||||
InfixOperator.BooleanOr -> return left || right
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
if (left !is Number || right !is Number) {
|
||||
throw RuntimeException("Failed to evaluate infix operation, bad types.")
|
||||
}
|
||||
@ -311,7 +319,7 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
||||
InfixOperator.Minus -> subtract(convert(left), convert(right))
|
||||
InfixOperator.Multiply -> multiply(convert(left), convert(right))
|
||||
InfixOperator.Divide -> divide(convert(left), convert(right))
|
||||
InfixOperator.Equals, InfixOperator.NotEquals -> throw RuntimeException("Unable to handle operation $op")
|
||||
InfixOperator.Equals, InfixOperator.NotEquals, InfixOperator.BooleanAnd, InfixOperator.BooleanOr -> throw RuntimeException("Unable to handle operation $op")
|
||||
InfixOperator.BinaryAnd -> binaryAnd(convert(left), convert(right))
|
||||
InfixOperator.BinaryOr -> binaryOr(convert(left), convert(right))
|
||||
InfixOperator.BinaryExclusiveOr -> binaryExclusiveOr(convert(left), convert(right))
|
||||
@ -333,7 +341,7 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
||||
binaryNot: (T) -> T
|
||||
): Any {
|
||||
return when (op) {
|
||||
PrefixOperator.Negate -> throw RuntimeException("Unable to handle operation $op")
|
||||
PrefixOperator.BooleanNot -> throw RuntimeException("Unable to handle operation $op")
|
||||
PrefixOperator.UnaryPlus -> plus(convert(value))
|
||||
PrefixOperator.UnaryMinus -> minus(convert(value))
|
||||
PrefixOperator.BinaryNot -> binaryNot(convert(value))
|
||||
|
33
examples/boolean.pork
Normal file
33
examples/boolean.pork
Normal file
@ -0,0 +1,33 @@
|
||||
func buildRow(str, a, b, c, d) {
|
||||
let checkSeparator = "| "
|
||||
print("|", str, checkSeparator)
|
||||
if a { print("✅") } else { print("🚫") }
|
||||
print(checkSeparator)
|
||||
if b { print("✅") } else { print("🚫") }
|
||||
print(checkSeparator)
|
||||
if c { print("✅") } else { print("🚫") }
|
||||
print(checkSeparator)
|
||||
if d { print("✅") } else { print("🚫") }
|
||||
println("|")
|
||||
}
|
||||
|
||||
export func main() {
|
||||
println("| | a=🚫 b=🚫| a=✅b=🚫| a=🚫b=✅| a=✅b=✅|")
|
||||
buildRow(" a == b", false == false, true == false, false == true, true == true)
|
||||
buildRow("!a == b", (not false) == false, (not true) == false, (not false) == true, (not true) == true)
|
||||
buildRow(" a == !b", false == (not false), true == (not false), false == (not true), true == (not true))
|
||||
buildRow("!a == !b", (not false) == (not false), (not true) == (not false), (not false) == (not true), (not true) == (not true))
|
||||
buildRow(" a != b", false != false, true != false, false != true, true != true)
|
||||
buildRow("!a != b", (not false) != false, (not true) != false, (not false) != true, (not true) != true)
|
||||
buildRow(" a != !b", false != (not false), true != (not false), false != (not true), true != (not true))
|
||||
buildRow("!a != !b", (not false) != (not false), (not true) != (not false), (not false) != (not true), (not true) != (not true))
|
||||
buildRow(" a && b", false and false, true and false, false and true, true and true)
|
||||
buildRow("!a && b", (not false) and false, (not true) and false, (not false) and true, (not true) and true)
|
||||
buildRow(" a && !b", false and (not false), true and (not false), false and (not true), true and (not true))
|
||||
buildRow("!a && !b", (not false) and (not false), (not true) and (not false), (not false) and (not true), (not true) and (not true))
|
||||
buildRow(" a || b", false or false, true or false, false or true, true or true)
|
||||
buildRow("!a || b", (not false) or false, (not true) or false, (not false) or true, (not true) or true)
|
||||
buildRow(" a || !b", false or (not false), true or (not false), false or (not true), true or (not true))
|
||||
buildRow("!a || !b", (not false) or (not false), (not true) or (not false), (not false) or (not true), (not true) or (not true))
|
||||
println("|-----------------------------------------------------|")
|
||||
}
|
@ -83,7 +83,7 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
|
||||
}
|
||||
|
||||
private fun readPrefixOperation(): PrefixOperation = within {
|
||||
expect(TokenType.Negation, TokenType.Plus, TokenType.Minus, TokenType.Tilde) {
|
||||
expect(TokenType.Not, TokenType.Plus, TokenType.Minus, TokenType.Tilde) {
|
||||
PrefixOperation(convertPrefixOperator(it), readExpression())
|
||||
}
|
||||
}
|
||||
@ -157,7 +157,7 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
|
||||
readParentheses()
|
||||
}
|
||||
|
||||
TokenType.Negation, TokenType.Plus, TokenType.Minus, TokenType.Tilde -> {
|
||||
TokenType.Not, TokenType.Plus, TokenType.Minus, TokenType.Tilde -> {
|
||||
readPrefixOperation()
|
||||
}
|
||||
|
||||
@ -215,7 +215,9 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
|
||||
TokenType.Lesser,
|
||||
TokenType.Greater,
|
||||
TokenType.LesserEqual,
|
||||
TokenType.GreaterEqual
|
||||
TokenType.GreaterEqual,
|
||||
TokenType.And,
|
||||
TokenType.Or
|
||||
)
|
||||
) {
|
||||
within {
|
||||
@ -338,10 +340,13 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
|
||||
TokenType.Greater -> InfixOperator.Greater
|
||||
TokenType.LesserEqual -> InfixOperator.LesserEqual
|
||||
TokenType.GreaterEqual -> InfixOperator.GreaterEqual
|
||||
TokenType.And -> InfixOperator.BooleanAnd
|
||||
TokenType.Or -> InfixOperator.BooleanOr
|
||||
else -> throw RuntimeException("Unknown Infix Operator")
|
||||
}
|
||||
|
||||
private fun convertPrefixOperator(token: Token): PrefixOperator = when (token.type) {
|
||||
TokenType.Not -> PrefixOperator.BooleanNot
|
||||
TokenType.Plus -> PrefixOperator.UnaryPlus
|
||||
TokenType.Minus -> PrefixOperator.UnaryMinus
|
||||
TokenType.Tilde -> PrefixOperator.BinaryNot
|
||||
|
@ -13,7 +13,8 @@ enum class TokenType(vararg properties: TokenTypeProperty) {
|
||||
(it in '0' .. '9')}, KeywordUpgrader),
|
||||
StringLiteral(StringLiteralFamily),
|
||||
Equality(OperatorFamily),
|
||||
Inequality(OperatorFamily),
|
||||
Inequality(ManyChars("!="), OperatorFamily),
|
||||
ExclaimationPoint(SingleChar('!'), Promotion('=', Inequality)),
|
||||
Equals(SingleChar('='), Promotion('=', Equality)),
|
||||
PlusPlus(ManyChars("++"), OperatorFamily),
|
||||
MinusMinus(ManyChars("--"), OperatorFamily),
|
||||
@ -21,6 +22,8 @@ enum class TokenType(vararg properties: TokenTypeProperty) {
|
||||
Minus(SingleChar('-'), OperatorFamily, Promotion('-', MinusMinus)),
|
||||
Multiply(SingleChar('*'), OperatorFamily),
|
||||
Divide(SingleChar('/'), OperatorFamily),
|
||||
And(ManyChars("and"), OperatorFamily),
|
||||
Or(ManyChars("or"), OperatorFamily),
|
||||
Tilde(SingleChar('~'), OperatorFamily),
|
||||
Ampersand(SingleChar('&'), OperatorFamily),
|
||||
Pipe(SingleChar('|'), OperatorFamily),
|
||||
@ -35,7 +38,7 @@ enum class TokenType(vararg properties: TokenTypeProperty) {
|
||||
RightBracket(SingleChar(']')),
|
||||
LeftParentheses(SingleChar('(')),
|
||||
RightParentheses(SingleChar(')')),
|
||||
Negation(SingleChar('!'), Promotion('=', Inequality), OperatorFamily),
|
||||
Not(ManyChars("not"), OperatorFamily),
|
||||
Mod(ManyChars("mod"), OperatorFamily),
|
||||
Rem(ManyChars("rem"), OperatorFamily),
|
||||
Comma(SingleChar(',')),
|
||||
|
Loading…
Reference in New Issue
Block a user