Skip to content

Commit

Permalink
feat(compiler): add FunctionStatementProcessor and refactor related c…
Browse files Browse the repository at this point in the history
…lasses #24

- Introduced a new class FunctionStatementProcessor to handle function statements.
- Refactored QueryStatementProcessor to extend FunctionStatementProcessor, removing duplicate code.
- Updated HobbitHole and ShireLifecycleTest to accommodate changes in function execution.
- Modified TaskRoutes to use the new FunctionStatementProcessor.
- Adjusted PatternActionProcessor to use the refactored QueryStatementProcessor.
  • Loading branch information
phodal committed Jun 28, 2024
1 parent 42d8326 commit 1179c5e
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 126 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ package com.phodal.shirelang.compiler.hobbit
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.execution.ui.ConsoleView
import com.intellij.execution.ui.ConsoleViewContentType
import com.intellij.openapi.application.runInEdt
import com.intellij.openapi.application.runReadAction
import com.intellij.openapi.application.smartReadAction
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.DumbAwareAction
import com.intellij.openapi.project.Project
Expand Down Expand Up @@ -123,7 +121,7 @@ open class HobbitHole(
console: ConsoleView?,
context: PostCodeHandleContext,
) {
// afterStreaming?.execute(myProject, console, context)
afterStreaming?.execute(myProject, console, context, this)
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,28 @@
package com.phodal.shirelang.compiler.hobbit.ast

import com.intellij.execution.ui.ConsoleView
import com.intellij.openapi.project.Project
import com.phodal.shirecore.middleware.PostCodeHandleContext
import com.phodal.shirelang.compiler.hobbit.HobbitHole
import com.phodal.shirelang.compiler.patternaction.FunctionStatementProcessor
import com.phodal.shirelang.compiler.patternaction.QueryStatementProcessor


data class TaskRoutesContext(
/**
* the LLM output
*/
val output: String,
)

data class Condition(
val conditionKey: String,
val valueExpression: FrontMatterType.EXPRESSION,
)

sealed class Task(open val expression: FrontMatterType.EXPRESSION?) {
class Default(override val expression: FrontMatterType.EXPRESSION?) : Task(expression)
class CustomTask(override val expression: FrontMatterType.EXPRESSION?) : Task(expression)
class Default(override val expression: FrontMatterType.EXPRESSION?) : Task(expression)
}

data class Case(
Expand All @@ -20,6 +35,29 @@ data class TaskRoutes(
val cases: List<Case>,
val defaultTask: Task,
) {
fun execute(myProject: Project, console: ConsoleView?, context: PostCodeHandleContext, hobbitHole: HobbitHole): Case? {
val conditionResult = mutableMapOf<String, Any>()

val processor = FunctionStatementProcessor(myProject, hobbitHole)
conditions.forEach {
val statement = it.valueExpression.value as Statement
val result = processor.execute(statement, conditionResult)
conditionResult[it.conditionKey] = result
}

val matchedCase = cases.find {
val caseKey = it.caseKey
val caseValue = it.valueExpression

val caseStatement = caseValue.expression?.value as Statement
val result = processor.execute(caseStatement, conditionResult)

conditionResult[caseKey] == result
}

return matchedCase
}

companion object {
fun from(expression: FrontMatterType.ARRAY): TaskRoutes? {
val arrays = expression.value as List<FrontMatterType>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package com.phodal.shirelang.compiler.patternaction

import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.project.Project
import com.phodal.shirelang.compiler.hobbit.HobbitHole
import com.phodal.shirelang.compiler.hobbit.ast.*

open class FunctionStatementProcessor(myProject: Project, hole: HobbitHole) {
fun execute(statement: Statement, emptyMap: Any): Any {
return this.processStatement(statement, emptyMap as Map<String, List<Any>>)
}

fun <T : Any> processStatement(
statement: Statement,
variables: Map<String, List<T>>,
): List<T> {
val result = mutableListOf<T>()
variables.forEach { (variableName, elements) ->
elements.forEach { element ->
when (statement) {
is Comparison -> {
val operator = statement.operator
val left = evaluate(statement.left, element)
val right = evaluate(statement.right, element)

when (operator.type) {
OperatorType.Equal -> {
if (left != null && left == right) {
result.add(element)
}
}

OperatorType.And -> {
if (left != null && left == right) {
result.add(element)
}
}

OperatorType.GreaterEqual -> {
if (left as Comparable<Any> >= right as Comparable<Any>) {
result.add(element)
}
}

OperatorType.GreaterThan -> {
if (left as Comparable<Any> > right as Comparable<Any>) {
result.add(element)
}
}

OperatorType.LessEqual -> {
if (left as Comparable<Any> <= right as Comparable<Any>) {
result.add(element)
}
}

OperatorType.LessThan -> {
if (left as Comparable<Any> < right as Comparable<Any>) {
result.add(element)
}
}

OperatorType.NotEqual -> {
if (left != null && left != right) {
result.add(element)
}
}

OperatorType.Or -> {
if (left == true || right == true) {
result.add(element)
}
}

else -> {
logger<QueryStatementProcessor>().warn("unknown operator: $operator")
}
}
}

else -> {
logger<QueryStatementProcessor>().warn("unknown statement: $statement")
}
}
}
}

return result
}

fun <T : Any> evaluate(type: FrontMatterType, element: T): Any? {
return when (type) {
is FrontMatterType.ARRAY -> {
(type.value as List<FrontMatterType>).map {
evaluate(it, element)
}
}

is FrontMatterType.EXPRESSION -> {
evalExpression(type, element)
}

is FrontMatterType.BOOLEAN,
is FrontMatterType.DATE,
is FrontMatterType.IDENTIFIER,
is FrontMatterType.NUMBER,
is FrontMatterType.STRING,
-> {
type.value
}

else -> {
throw IllegalArgumentException("unknown type: $type")
}
}
}

open fun <T : Any> evalExpression(type: FrontMatterType, element: T): Any? {
when (type.value) {
is MethodCall -> {
return invokeMethodOrField(type.value, element)
}

else -> {
throw IllegalArgumentException("unknown type: $type")
}
}
}

open fun <T : Any> invokeMethodOrField(methodCall: MethodCall, element: T): Any? {
//
return null
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class PatternActionProcessor(val myProject: Project, val editor: Editor, val hol
}

if (actionTransform.isQueryStatement) {
return QueryStatementProcessor(myProject, editor, hole).execute(actionTransform)
return QueryStatementProcessor(myProject, hole).execute(actionTransform)
}

var input: Any = ""
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,31 @@
package com.phodal.shirelang.compiler.patternaction

import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import com.phodal.shirecore.provider.shire.ShireSymbolProvider
import com.phodal.shirelang.compiler.hobbit.HobbitHole
import com.phodal.shirelang.compiler.hobbit.ast.*
import java.util.*

class QueryStatementProcessor(val myProject: Project, editor: Editor, hole: HobbitHole) {
class QueryStatementProcessor(val myProject: Project, hole: HobbitHole) : FunctionStatementProcessor(myProject, hole) {
fun execute(transform: PatternActionTransform): String {
val fromStmt = transform.patternActionFuncs.find { it is PatternActionFunc.From } as PatternActionFunc.From
val selectStmt =
transform.patternActionFuncs.find { it is PatternActionFunc.Select } as PatternActionFunc.Select
val whereStmt = transform.patternActionFuncs.find { it is PatternActionFunc.Where } as PatternActionFunc.Where

val variables: Map<String, List<PsiElement>> = buildVariables(fromStmt)
val handledElements = processCondition(whereStmt.statement, variables)
val handledElements = processStatement(whereStmt.statement, variables)
val selectElements = processSelect(selectStmt, handledElements)

return selectElements.joinToString("\n")
}

fun execute(expression: Statement, variables: Map<String, List<PsiElement>>): List<PsiElement> {
return processStatement(expression, variables)
}

private fun buildVariables(fromStmt: PatternActionFunc.From): Map<String, List<PsiElement>> {
return fromStmt.variables.associate {
it.value to lookupElement(it)
Expand All @@ -45,97 +48,7 @@ class QueryStatementProcessor(val myProject: Project, editor: Editor, hole: Hobb
return elements
}

private fun processCondition(
whereStmt: Statement,
variables: Map<String, List<PsiElement>>,
): List<PsiElement> {
val result = mutableListOf<PsiElement>()
variables.forEach { (variableName, elements) ->
elements.forEach { element ->
when (whereStmt) {
is Comparison -> {
val operator = whereStmt.operator
val left = evaluate(whereStmt.left, element)
val right = evaluate(whereStmt.right, element)

when (operator.type) {
OperatorType.Equal -> {
if (left != null && left == right) {
result.add(element)
}
}

OperatorType.And -> {
if (left != null && left == right) {
result.add(element)
}
}

OperatorType.GreaterEqual -> {
if (left as Comparable<Any> >= right as Comparable<Any>) {
result.add(element)
}
}

OperatorType.GreaterThan -> {
if (left as Comparable<Any> > right as Comparable<Any>) {
result.add(element)
}
}

OperatorType.LessEqual -> {
if (left as Comparable<Any> <= right as Comparable<Any>) {
result.add(element)
}
}

OperatorType.LessThan -> {
if (left as Comparable<Any> < right as Comparable<Any>) {
result.add(element)
}
}

OperatorType.NotEqual -> {
if (left != null && left != right) {
result.add(element)
}
}

OperatorType.Or -> {
if (left == true || right == true) {
result.add(element)
}
}

else -> {
logger<QueryStatementProcessor>().warn("unknown operator: $operator")
}
}
}

else -> {
logger<QueryStatementProcessor>().warn("unknown statement: $whereStmt")
}
}
}
}

return result
}

private fun evalExpression(type: FrontMatterType, element: PsiElement): Any? {
when (type.value) {
is MethodCall -> {
return invokeMethodOrField(type.value, element)
}

else -> {
throw IllegalArgumentException("unknown type: $type")
}
}
}

private fun invokeMethodOrField(methodCall: MethodCall, element: PsiElement): Any? {
override fun <T : Any> invokeMethodOrField(methodCall: MethodCall, element: T): Any? {
val methodName = methodCall.methodName.display()
val methodArgs = methodCall.arguments

Expand Down Expand Up @@ -193,33 +106,6 @@ class QueryStatementProcessor(val myProject: Project, editor: Editor, hole: Hobb
return null
}

private fun evaluate(type: FrontMatterType, element: PsiElement): Any? {
return when (type) {
is FrontMatterType.ARRAY -> {
(type.value as List<FrontMatterType>).map {
evaluate(it, element)
}
}

is FrontMatterType.EXPRESSION -> {
evalExpression(type, element)
}

is FrontMatterType.BOOLEAN,
is FrontMatterType.DATE,
is FrontMatterType.IDENTIFIER,
is FrontMatterType.NUMBER,
is FrontMatterType.STRING,
-> {
type.value
}

else -> {
throw IllegalArgumentException("unknown type: $type")
}
}
}

private fun processSelect(selectStmt: PatternActionFunc.Select, handledElements: List<PsiElement>): List<String> {
return selectStmt.statements.flatMap {
processSelectStatement(it, handledElements)
Expand Down
Loading

0 comments on commit 1179c5e

Please sign in to comment.