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
|
- name: LesserEqual
|
||||||
values:
|
values:
|
||||||
token: "<="
|
token: "<="
|
||||||
|
- name: BooleanAnd
|
||||||
|
values:
|
||||||
|
token: "and"
|
||||||
|
- name: BooleanOr
|
||||||
|
values:
|
||||||
|
token: "or"
|
||||||
- name: BinaryAnd
|
- name: BinaryAnd
|
||||||
values:
|
values:
|
||||||
token: "&"
|
token: "&"
|
||||||
@ -196,9 +202,9 @@ types:
|
|||||||
- name: token
|
- name: token
|
||||||
type: String
|
type: String
|
||||||
enums:
|
enums:
|
||||||
- name: Negate
|
- name: BooleanNot
|
||||||
values:
|
values:
|
||||||
token: "!"
|
token: "not"
|
||||||
- name: UnaryPlus
|
- name: UnaryPlus
|
||||||
values:
|
values:
|
||||||
token: "+"
|
token: "+"
|
||||||
|
@ -19,6 +19,8 @@ enum class InfixOperator(val token: String) {
|
|||||||
Greater(">"),
|
Greater(">"),
|
||||||
GreaterEqual(">="),
|
GreaterEqual(">="),
|
||||||
LesserEqual("<="),
|
LesserEqual("<="),
|
||||||
|
BooleanAnd("and"),
|
||||||
|
BooleanOr("or"),
|
||||||
BinaryAnd("&"),
|
BinaryAnd("&"),
|
||||||
BinaryOr("|"),
|
BinaryOr("|"),
|
||||||
BinaryExclusiveOr("^")
|
BinaryExclusiveOr("^")
|
||||||
|
@ -7,7 +7,7 @@ import kotlinx.serialization.Serializable
|
|||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("prefixOperator")
|
@SerialName("prefixOperator")
|
||||||
enum class PrefixOperator(val token: String) {
|
enum class PrefixOperator(val token: String) {
|
||||||
Negate("!"),
|
BooleanNot("not"),
|
||||||
UnaryPlus("+"),
|
UnaryPlus("+"),
|
||||||
UnaryMinus("-"),
|
UnaryMinus("-"),
|
||||||
BinaryNot("~")
|
BinaryNot("~")
|
||||||
|
@ -92,7 +92,7 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
|||||||
override fun visitPrefixOperation(node: PrefixOperation): Any {
|
override fun visitPrefixOperation(node: PrefixOperation): Any {
|
||||||
val value = node.expression.visit(this)
|
val value = node.expression.visit(this)
|
||||||
return when (node.op) {
|
return when (node.op) {
|
||||||
PrefixOperator.Negate -> {
|
PrefixOperator.BooleanNot -> {
|
||||||
if (value !is Boolean) {
|
if (value !is Boolean) {
|
||||||
throw RuntimeException("Cannot negate a value which is not a boolean.")
|
throw RuntimeException("Cannot negate a value which is not a boolean.")
|
||||||
}
|
}
|
||||||
@ -192,6 +192,14 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
|||||||
else -> {}
|
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) {
|
if (left !is Number || right !is Number) {
|
||||||
throw RuntimeException("Failed to evaluate infix operation, bad types.")
|
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.Minus -> subtract(convert(left), convert(right))
|
||||||
InfixOperator.Multiply -> multiply(convert(left), convert(right))
|
InfixOperator.Multiply -> multiply(convert(left), convert(right))
|
||||||
InfixOperator.Divide -> divide(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.BinaryAnd -> binaryAnd(convert(left), convert(right))
|
||||||
InfixOperator.BinaryOr -> binaryOr(convert(left), convert(right))
|
InfixOperator.BinaryOr -> binaryOr(convert(left), convert(right))
|
||||||
InfixOperator.BinaryExclusiveOr -> binaryExclusiveOr(convert(left), convert(right))
|
InfixOperator.BinaryExclusiveOr -> binaryExclusiveOr(convert(left), convert(right))
|
||||||
@ -333,7 +341,7 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
|
|||||||
binaryNot: (T) -> T
|
binaryNot: (T) -> T
|
||||||
): Any {
|
): Any {
|
||||||
return when (op) {
|
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.UnaryPlus -> plus(convert(value))
|
||||||
PrefixOperator.UnaryMinus -> minus(convert(value))
|
PrefixOperator.UnaryMinus -> minus(convert(value))
|
||||||
PrefixOperator.BinaryNot -> binaryNot(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 {
|
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())
|
PrefixOperation(convertPrefixOperator(it), readExpression())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -157,7 +157,7 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
|
|||||||
readParentheses()
|
readParentheses()
|
||||||
}
|
}
|
||||||
|
|
||||||
TokenType.Negation, TokenType.Plus, TokenType.Minus, TokenType.Tilde -> {
|
TokenType.Not, TokenType.Plus, TokenType.Minus, TokenType.Tilde -> {
|
||||||
readPrefixOperation()
|
readPrefixOperation()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,7 +215,9 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
|
|||||||
TokenType.Lesser,
|
TokenType.Lesser,
|
||||||
TokenType.Greater,
|
TokenType.Greater,
|
||||||
TokenType.LesserEqual,
|
TokenType.LesserEqual,
|
||||||
TokenType.GreaterEqual
|
TokenType.GreaterEqual,
|
||||||
|
TokenType.And,
|
||||||
|
TokenType.Or
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
within {
|
within {
|
||||||
@ -338,10 +340,13 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
|
|||||||
TokenType.Greater -> InfixOperator.Greater
|
TokenType.Greater -> InfixOperator.Greater
|
||||||
TokenType.LesserEqual -> InfixOperator.LesserEqual
|
TokenType.LesserEqual -> InfixOperator.LesserEqual
|
||||||
TokenType.GreaterEqual -> InfixOperator.GreaterEqual
|
TokenType.GreaterEqual -> InfixOperator.GreaterEqual
|
||||||
|
TokenType.And -> InfixOperator.BooleanAnd
|
||||||
|
TokenType.Or -> InfixOperator.BooleanOr
|
||||||
else -> throw RuntimeException("Unknown Infix Operator")
|
else -> throw RuntimeException("Unknown Infix Operator")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun convertPrefixOperator(token: Token): PrefixOperator = when (token.type) {
|
private fun convertPrefixOperator(token: Token): PrefixOperator = when (token.type) {
|
||||||
|
TokenType.Not -> PrefixOperator.BooleanNot
|
||||||
TokenType.Plus -> PrefixOperator.UnaryPlus
|
TokenType.Plus -> PrefixOperator.UnaryPlus
|
||||||
TokenType.Minus -> PrefixOperator.UnaryMinus
|
TokenType.Minus -> PrefixOperator.UnaryMinus
|
||||||
TokenType.Tilde -> PrefixOperator.BinaryNot
|
TokenType.Tilde -> PrefixOperator.BinaryNot
|
||||||
|
@ -13,7 +13,8 @@ enum class TokenType(vararg properties: TokenTypeProperty) {
|
|||||||
(it in '0' .. '9')}, KeywordUpgrader),
|
(it in '0' .. '9')}, KeywordUpgrader),
|
||||||
StringLiteral(StringLiteralFamily),
|
StringLiteral(StringLiteralFamily),
|
||||||
Equality(OperatorFamily),
|
Equality(OperatorFamily),
|
||||||
Inequality(OperatorFamily),
|
Inequality(ManyChars("!="), OperatorFamily),
|
||||||
|
ExclaimationPoint(SingleChar('!'), Promotion('=', Inequality)),
|
||||||
Equals(SingleChar('='), Promotion('=', Equality)),
|
Equals(SingleChar('='), Promotion('=', Equality)),
|
||||||
PlusPlus(ManyChars("++"), OperatorFamily),
|
PlusPlus(ManyChars("++"), OperatorFamily),
|
||||||
MinusMinus(ManyChars("--"), OperatorFamily),
|
MinusMinus(ManyChars("--"), OperatorFamily),
|
||||||
@ -21,6 +22,8 @@ enum class TokenType(vararg properties: TokenTypeProperty) {
|
|||||||
Minus(SingleChar('-'), OperatorFamily, Promotion('-', MinusMinus)),
|
Minus(SingleChar('-'), OperatorFamily, Promotion('-', MinusMinus)),
|
||||||
Multiply(SingleChar('*'), OperatorFamily),
|
Multiply(SingleChar('*'), OperatorFamily),
|
||||||
Divide(SingleChar('/'), OperatorFamily),
|
Divide(SingleChar('/'), OperatorFamily),
|
||||||
|
And(ManyChars("and"), OperatorFamily),
|
||||||
|
Or(ManyChars("or"), OperatorFamily),
|
||||||
Tilde(SingleChar('~'), OperatorFamily),
|
Tilde(SingleChar('~'), OperatorFamily),
|
||||||
Ampersand(SingleChar('&'), OperatorFamily),
|
Ampersand(SingleChar('&'), OperatorFamily),
|
||||||
Pipe(SingleChar('|'), OperatorFamily),
|
Pipe(SingleChar('|'), OperatorFamily),
|
||||||
@ -35,7 +38,7 @@ enum class TokenType(vararg properties: TokenTypeProperty) {
|
|||||||
RightBracket(SingleChar(']')),
|
RightBracket(SingleChar(']')),
|
||||||
LeftParentheses(SingleChar('(')),
|
LeftParentheses(SingleChar('(')),
|
||||||
RightParentheses(SingleChar(')')),
|
RightParentheses(SingleChar(')')),
|
||||||
Negation(SingleChar('!'), Promotion('=', Inequality), OperatorFamily),
|
Not(ManyChars("not"), OperatorFamily),
|
||||||
Mod(ManyChars("mod"), OperatorFamily),
|
Mod(ManyChars("mod"), OperatorFamily),
|
||||||
Rem(ManyChars("rem"), OperatorFamily),
|
Rem(ManyChars("rem"), OperatorFamily),
|
||||||
Comma(SingleChar(',')),
|
Comma(SingleChar(',')),
|
||||||
|
Loading…
Reference in New Issue
Block a user