Skip to content

Commit

Permalink
Use ValueFactory.eval in .include
Browse files Browse the repository at this point in the history
  • Loading branch information
iamgio committed Jul 3, 2024
1 parent 7dbd1d7 commit 6388fcc
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -241,43 +241,6 @@ object ValueFactory {
expandFunctionCalls = true,
).asInline()

/**
* Evaluates an expression from a raw string input.
* @param raw string input that may contain both static values and function calls (e.g. `"2 + 2 is .sum {2} {2}"`)
* @param context context to retrieve the pipeline from
* @return the expression (in the previous example: `ComposedExpression(DynamicValue("2 + 2 is "), FunctionCall(sum, 2, 2))`)
*/
fun expression(
raw: String,
context: Context,
): Expression? {
// The content of the argument is tokenized to distinguish static values (string/number/...)
// from nested function calls, which are also expressions.
val components =
this.markdown(
lexer = context.flavor.lexerFactory.newExpressionLexer(raw, allowBlockFunctionCalls = true),
context,
expandFunctionCalls = false,
).unwrappedValue.children

if (components.isEmpty()) return null

/**
* @param node to convert
* @return an expression that matches the node type
*/
fun nodeToExpression(node: Node): Expression =
when (node) {
is PlainTextNode -> DynamicValue(node.text) // The actual type is determined later.
is FunctionCallNode -> context.resolveUnchecked(node) // Function existance is checked later.

else -> throw IllegalArgumentException("Unexpected node $node in expression $raw")
}

// Nodes are mapped to expressions.
return ComposedExpression(expressions = components.map(::nodeToExpression))
}

/**
* @param raw string input to parse the expression from
* @param context context to retrieve the pipeline from
Expand Down Expand Up @@ -344,6 +307,43 @@ object ValueFactory {
)
}

/**
* Evaluates an expression from a raw string input.
* @param raw string input that may contain both static values and function calls (e.g. `"2 + 2 is .sum {2} {2}"`)
* @param context context to retrieve the pipeline from
* @return the expression (in the previous example: `ComposedExpression(DynamicValue("2 + 2 is "), FunctionCall(sum, 2, 2))`)
*/
fun expression(
raw: String,
context: Context,
): Expression? {
// The content of the argument is tokenized to distinguish static values (string/number/...)
// from nested function calls, which are also expressions.
val components =
this.markdown(
lexer = context.flavor.lexerFactory.newExpressionLexer(raw, allowBlockFunctionCalls = true),
context,
expandFunctionCalls = false,
).unwrappedValue.children

if (components.isEmpty()) return null

/**
* @param node to convert
* @return an expression that matches the node type
*/
fun nodeToExpression(node: Node): Expression =
when (node) {
is PlainTextNode -> DynamicValue(node.text) // The actual type is determined later.
is FunctionCallNode -> context.resolveUnchecked(node) // Function existance is checked later.

else -> throw IllegalArgumentException("Unexpected node $node in expression $raw")
}

// Nodes are mapped to expressions.
return ComposedExpression(expressions = components.map(::nodeToExpression))
}

/**
* Evaluates an expression from a raw string input.
* @param raw string input that may contain both static values and function calls (e.g. `"2 + 2 is .sum {2} {2}"`)
Expand Down
12 changes: 1 addition & 11 deletions stdlib/src/main/kotlin/eu/iamgio/quarkdown/stdlib/Ecosystem.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package eu.iamgio.quarkdown.stdlib

import eu.iamgio.quarkdown.context.Context
import eu.iamgio.quarkdown.function.error.FunctionRuntimeException
import eu.iamgio.quarkdown.function.expression.eval
import eu.iamgio.quarkdown.function.reflect.Injected
import eu.iamgio.quarkdown.function.value.OutputValue
import eu.iamgio.quarkdown.function.value.ValueFactory
Expand Down Expand Up @@ -36,14 +35,5 @@ fun include(
// Evaluate the Quarkdown source.
// This automatically converts the source into a value (e.g. a node, a string, a number, etc.)
// and fills the current context with new declarations (e.g. variables, functions, link definitions, etc.)
val result =
ValueFactory.expression(raw, context)?.eval()
?: throw FunctionRuntimeException("Cannot include sub-file $file: the Quarkdown source could not be evaluated")

// The value must be an output value in order to comply with the function rules.
return result as? OutputValue<*>
?: throw FunctionRuntimeException(
"Cannot include sub-file $file: the evaluation of the Quarkdown source is not a suitable output value " +
"(${result::class.simpleName} found)",
)
return ValueFactory.eval(raw, context)
}

0 comments on commit 6388fcc

Please sign in to comment.