mirror of
				https://github.com/GayPizzaSpecifications/pork.git
				synced 2025-11-03 17:39:38 +00:00 
			
		
		
		
	language: implement for in
This commit is contained in:
		@ -250,6 +250,15 @@ types:
 | 
				
			|||||||
      type: Expression
 | 
					      type: Expression
 | 
				
			||||||
    - name: block
 | 
					    - name: block
 | 
				
			||||||
      type: Block
 | 
					      type: Block
 | 
				
			||||||
 | 
					  ForIn:
 | 
				
			||||||
 | 
					    parent: Expression
 | 
				
			||||||
 | 
					    values:
 | 
				
			||||||
 | 
					    - name: symbol
 | 
				
			||||||
 | 
					      type: Symbol
 | 
				
			||||||
 | 
					    - name: expression
 | 
				
			||||||
 | 
					      type: Expression
 | 
				
			||||||
 | 
					    - name: block
 | 
				
			||||||
 | 
					      type: Block
 | 
				
			||||||
  Break:
 | 
					  Break:
 | 
				
			||||||
    parent: Expression
 | 
					    parent: Expression
 | 
				
			||||||
    values: []
 | 
					    values: []
 | 
				
			||||||
 | 
				
			|||||||
@ -30,6 +30,7 @@ digraph A {
 | 
				
			|||||||
  type_StringLiteral [shape=box,label="StringLiteral"]
 | 
					  type_StringLiteral [shape=box,label="StringLiteral"]
 | 
				
			||||||
  type_SymbolReference [shape=box,label="SymbolReference"]
 | 
					  type_SymbolReference [shape=box,label="SymbolReference"]
 | 
				
			||||||
  type_While [shape=box,label="While"]
 | 
					  type_While [shape=box,label="While"]
 | 
				
			||||||
 | 
					  type_ForIn [shape=box,label="ForIn"]
 | 
				
			||||||
  type_Break [shape=box,label="Break"]
 | 
					  type_Break [shape=box,label="Break"]
 | 
				
			||||||
  type_Continue [shape=box,label="Continue"]
 | 
					  type_Continue [shape=box,label="Continue"]
 | 
				
			||||||
  type_Native [shape=box,label="Native"]
 | 
					  type_Native [shape=box,label="Native"]
 | 
				
			||||||
@ -56,6 +57,7 @@ digraph A {
 | 
				
			|||||||
  type_Expression -> type_StringLiteral
 | 
					  type_Expression -> type_StringLiteral
 | 
				
			||||||
  type_Expression -> type_SymbolReference
 | 
					  type_Expression -> type_SymbolReference
 | 
				
			||||||
  type_Expression -> type_While
 | 
					  type_Expression -> type_While
 | 
				
			||||||
 | 
					  type_Expression -> type_ForIn
 | 
				
			||||||
  type_Expression -> type_Break
 | 
					  type_Expression -> type_Break
 | 
				
			||||||
  type_Expression -> type_Continue
 | 
					  type_Expression -> type_Continue
 | 
				
			||||||
  type_Definition -> type_FunctionDefinition
 | 
					  type_Definition -> type_FunctionDefinition
 | 
				
			||||||
@ -97,6 +99,9 @@ digraph A {
 | 
				
			|||||||
  type_SymbolReference -> type_Symbol [style=dotted]
 | 
					  type_SymbolReference -> type_Symbol [style=dotted]
 | 
				
			||||||
  type_While -> type_Expression [style=dotted]
 | 
					  type_While -> type_Expression [style=dotted]
 | 
				
			||||||
  type_While -> type_Block [style=dotted]
 | 
					  type_While -> type_Block [style=dotted]
 | 
				
			||||||
 | 
					  type_ForIn -> type_Symbol [style=dotted]
 | 
				
			||||||
 | 
					  type_ForIn -> type_Expression [style=dotted]
 | 
				
			||||||
 | 
					  type_ForIn -> type_Block [style=dotted]
 | 
				
			||||||
  type_Native -> type_Symbol [style=dotted]
 | 
					  type_Native -> type_Symbol [style=dotted]
 | 
				
			||||||
  type_Native -> type_StringLiteral [style=dotted]
 | 
					  type_Native -> type_StringLiteral [style=dotted]
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										30
									
								
								ast/src/main/kotlin/gay/pizza/pork/ast/ForIn.kt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								ast/src/main/kotlin/gay/pizza/pork/ast/ForIn.kt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					// GENERATED CODE FROM PORK AST CODEGEN
 | 
				
			||||||
 | 
					package gay.pizza.pork.ast
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import kotlinx.serialization.SerialName
 | 
				
			||||||
 | 
					import kotlinx.serialization.Serializable
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Serializable
 | 
				
			||||||
 | 
					@SerialName("forIn")
 | 
				
			||||||
 | 
					class ForIn(val symbol: Symbol, val expression: Expression, val block: Block) : Expression() {
 | 
				
			||||||
 | 
					  override val type: NodeType = NodeType.ForIn
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  override fun <T> visitChildren(visitor: NodeVisitor<T>): List<T> =
 | 
				
			||||||
 | 
					    visitor.visitNodes(symbol, expression, block)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  override fun <T> visit(visitor: NodeVisitor<T>): T =
 | 
				
			||||||
 | 
					    visitor.visitForIn(this)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  override fun equals(other: Any?): Boolean {
 | 
				
			||||||
 | 
					    if (other !is ForIn) return false
 | 
				
			||||||
 | 
					    return other.symbol == symbol && other.expression == expression && other.block == block
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  override fun hashCode(): Int {
 | 
				
			||||||
 | 
					    var result = symbol.hashCode()
 | 
				
			||||||
 | 
					    result = 31 * result + expression.hashCode()
 | 
				
			||||||
 | 
					    result = 31 * result + block.hashCode()
 | 
				
			||||||
 | 
					    result = 31 * result + type.hashCode()
 | 
				
			||||||
 | 
					    return result
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -20,6 +20,9 @@ class NodeCoalescer(val handler: (Node) -> Unit) : NodeVisitor<Unit> {
 | 
				
			|||||||
  override fun visitDoubleLiteral(node: DoubleLiteral): Unit =
 | 
					  override fun visitDoubleLiteral(node: DoubleLiteral): Unit =
 | 
				
			||||||
    handle(node)
 | 
					    handle(node)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  override fun visitForIn(node: ForIn): Unit =
 | 
				
			||||||
 | 
					    handle(node)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  override fun visitFunctionCall(node: FunctionCall): Unit =
 | 
					  override fun visitFunctionCall(node: FunctionCall): Unit =
 | 
				
			||||||
    handle(node)
 | 
					    handle(node)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -12,6 +12,7 @@ enum class NodeType(val parent: NodeType? = null) {
 | 
				
			|||||||
  Declaration(Node),
 | 
					  Declaration(Node),
 | 
				
			||||||
  Definition(Node),
 | 
					  Definition(Node),
 | 
				
			||||||
  DoubleLiteral(Expression),
 | 
					  DoubleLiteral(Expression),
 | 
				
			||||||
 | 
					  ForIn(Expression),
 | 
				
			||||||
  FunctionCall(Expression),
 | 
					  FunctionCall(Expression),
 | 
				
			||||||
  FunctionDefinition(Definition),
 | 
					  FunctionDefinition(Definition),
 | 
				
			||||||
  If(Expression),
 | 
					  If(Expression),
 | 
				
			||||||
 | 
				
			|||||||
@ -14,6 +14,8 @@ interface NodeVisitor<T> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  fun visitDoubleLiteral(node: DoubleLiteral): T
 | 
					  fun visitDoubleLiteral(node: DoubleLiteral): T
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  fun visitForIn(node: ForIn): T
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  fun visitFunctionCall(node: FunctionCall): T
 | 
					  fun visitFunctionCall(node: FunctionCall): T
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  fun visitFunctionDefinition(node: FunctionDefinition): T
 | 
					  fun visitFunctionDefinition(node: FunctionDefinition): T
 | 
				
			||||||
 | 
				
			|||||||
@ -25,6 +25,7 @@ fun <T> NodeVisitor<T>.visit(node: Node): T =
 | 
				
			|||||||
    is StringLiteral -> visitStringLiteral(node)
 | 
					    is StringLiteral -> visitStringLiteral(node)
 | 
				
			||||||
    is SymbolReference -> visitSymbolReference(node)
 | 
					    is SymbolReference -> visitSymbolReference(node)
 | 
				
			||||||
    is While -> visitWhile(node)
 | 
					    is While -> visitWhile(node)
 | 
				
			||||||
 | 
					    is ForIn -> visitForIn(node)
 | 
				
			||||||
    is Break -> visitBreak(node)
 | 
					    is Break -> visitBreak(node)
 | 
				
			||||||
    is Continue -> visitContinue(node)
 | 
					    is Continue -> visitContinue(node)
 | 
				
			||||||
    is Native -> visitNative(node)
 | 
					    is Native -> visitNative(node)
 | 
				
			||||||
 | 
				
			|||||||
@ -8,6 +8,29 @@ class EvaluationVisitor(root: Scope) : NodeVisitor<Any> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  override fun visitIntegerLiteral(node: IntegerLiteral): Any = node.value
 | 
					  override fun visitIntegerLiteral(node: IntegerLiteral): Any = node.value
 | 
				
			||||||
  override fun visitDoubleLiteral(node: DoubleLiteral): Any = node.value
 | 
					  override fun visitDoubleLiteral(node: DoubleLiteral): Any = node.value
 | 
				
			||||||
 | 
					  override fun visitForIn(node: ForIn): Any {
 | 
				
			||||||
 | 
					    val blockFunction = node.block.visit(this) as BlockFunction
 | 
				
			||||||
 | 
					    var result: Any? = null
 | 
				
			||||||
 | 
					    val value = node.expression.visit(this)
 | 
				
			||||||
 | 
					    if (value !is Iterable<*>) {
 | 
				
			||||||
 | 
					      throw RuntimeException("Unable to iterate on value that is not a iterable.")
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (item in value) {
 | 
				
			||||||
 | 
					      try {
 | 
				
			||||||
 | 
					        scoped {
 | 
				
			||||||
 | 
					          currentScope.define(node.symbol.id, item ?: None)
 | 
				
			||||||
 | 
					          result = blockFunction.call()
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      } catch (_: BreakMarker) {
 | 
				
			||||||
 | 
					        break
 | 
				
			||||||
 | 
					      } catch (_: ContinueMarker) {
 | 
				
			||||||
 | 
					        continue
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return result ?: None
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  override fun visitStringLiteral(node: StringLiteral): Any = node.text
 | 
					  override fun visitStringLiteral(node: StringLiteral): Any = node.text
 | 
				
			||||||
  override fun visitBooleanLiteral(node: BooleanLiteral): Any = node.value
 | 
					  override fun visitBooleanLiteral(node: BooleanLiteral): Any = node.value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										7
									
								
								examples/for.pork
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								examples/for.pork
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					let items = ["Hello", "Goodbye"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export func main() {
 | 
				
			||||||
 | 
					  for item in items {
 | 
				
			||||||
 | 
					    println(item)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -106,6 +106,15 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
 | 
				
			|||||||
    While(condition, block)
 | 
					    While(condition, block)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private fun readForIn(): ForIn = within {
 | 
				
			||||||
 | 
					    expect(TokenType.For)
 | 
				
			||||||
 | 
					    val symbol = readSymbolRaw()
 | 
				
			||||||
 | 
					    expect(TokenType.In)
 | 
				
			||||||
 | 
					    val value = readExpression()
 | 
				
			||||||
 | 
					    val block = readBlock()
 | 
				
			||||||
 | 
					    ForIn(symbol, value, block)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private fun readNative(): Native = within {
 | 
					  private fun readNative(): Native = within {
 | 
				
			||||||
    expect(TokenType.Native)
 | 
					    expect(TokenType.Native)
 | 
				
			||||||
    val form = readSymbolRaw()
 | 
					    val form = readSymbolRaw()
 | 
				
			||||||
@ -160,6 +169,10 @@ class Parser(source: PeekableSource<Token>, val attribution: NodeAttribution) {
 | 
				
			|||||||
        readWhile()
 | 
					        readWhile()
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      TokenType.For -> {
 | 
				
			||||||
 | 
					        readForIn()
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      TokenType.Break -> {
 | 
					      TokenType.Break -> {
 | 
				
			||||||
        expect(TokenType.Break)
 | 
					        expect(TokenType.Break)
 | 
				
			||||||
        Break()
 | 
					        Break()
 | 
				
			||||||
 | 
				
			|||||||
@ -28,6 +28,15 @@ class Printer(buffer: StringBuilder) : NodeVisitor<Unit> {
 | 
				
			|||||||
    append(node.value.toString())
 | 
					    append(node.value.toString())
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  override fun visitForIn(node: ForIn) {
 | 
				
			||||||
 | 
					    append("for ")
 | 
				
			||||||
 | 
					    visit(node.symbol)
 | 
				
			||||||
 | 
					    append(" in ")
 | 
				
			||||||
 | 
					    visit(node.expression)
 | 
				
			||||||
 | 
					    append(" ")
 | 
				
			||||||
 | 
					    visit(node.block)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  override fun visitStringLiteral(node: StringLiteral) {
 | 
					  override fun visitStringLiteral(node: StringLiteral) {
 | 
				
			||||||
    append("\"")
 | 
					    append("\"")
 | 
				
			||||||
    append(StringEscape.escape(node.text))
 | 
					    append(StringEscape.escape(node.text))
 | 
				
			||||||
 | 
				
			|||||||
@ -47,6 +47,8 @@ enum class TokenType(vararg properties: TokenTypeProperty) {
 | 
				
			|||||||
  If(ManyChars("if"), KeywordFamily),
 | 
					  If(ManyChars("if"), KeywordFamily),
 | 
				
			||||||
  Else(ManyChars("else"), KeywordFamily),
 | 
					  Else(ManyChars("else"), KeywordFamily),
 | 
				
			||||||
  While(ManyChars("while"), KeywordFamily),
 | 
					  While(ManyChars("while"), KeywordFamily),
 | 
				
			||||||
 | 
					  For(ManyChars("for"), KeywordFamily),
 | 
				
			||||||
 | 
					  In(ManyChars("in"), KeywordFamily),
 | 
				
			||||||
  Continue(ManyChars("continue"), KeywordFamily),
 | 
					  Continue(ManyChars("continue"), KeywordFamily),
 | 
				
			||||||
  Break(ManyChars("break"), KeywordFamily),
 | 
					  Break(ManyChars("break"), KeywordFamily),
 | 
				
			||||||
  Import(ManyChars("import"), KeywordFamily),
 | 
					  Import(ManyChars("import"), KeywordFamily),
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user