Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
90 lines (77 sloc) 3.29 KB
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using ServiceStack.Text;
namespace ServiceStack.Script
{
/// <summary>
/// Define a reusable
/// Usage: {{#function calc(a, b) }}
/// a * b | to => c
/// a + b + c | return
/// {{/function}}
/// </summary>
public class FunctionScriptBlock : ScriptBlock
{
public override string Name => "function";
public override ScriptLanguage Body => ScriptCode.Language;
public override Task WriteAsync(ScriptScopeContext scope, PageBlockFragment block, CancellationToken token)
{
// block.Argument key is unique to exact memory fragment, not string equality
var invokerCtx = (Tuple<string,StaticMethodInvoker>)scope.Context.CacheMemory.GetOrAdd(block.Argument, key => {
var literal = block.Argument.Span.ParseVarName(out var name);
var strName = name.ToString();
literal = literal.AdvancePastWhitespace();
literal = literal.AdvancePastWhitespace();
var args = TypeConstants.EmptyStringArray;
if (!literal.IsEmpty)
{
literal = literal.ParseArgumentsList(out var argIdentifiers);
args = new string[argIdentifiers.Count];
for (var i = 0; i < argIdentifiers.Count; i++)
{
args[i] = argIdentifiers[i].Name;
}
}
StaticMethodInvoker invoker = null;
// Allow recursion by initializing lazy Delegate
MethodInvoker LazyInvoker = (instance, paramValues) => {
if (invoker == null)
throw new NotSupportedException($"Uninitialized function '{strName}'");
return invoker(instance, paramValues);
};
invoker = (paramValues) => {
scope.PageResult.StackDepth++;
try
{
var page = new SharpPage(Context, block.Body);
var pageResult = new PageResult(page) {
Args = {
[strName] = LazyInvoker
},
StackDepth = scope.PageResult.StackDepth
};
var len = Math.Min(paramValues.Length, args.Length);
for (int i = 0; i < len; i++)
{
var paramValue = paramValues[i];
pageResult.Args[args[i]] = paramValue;
}
if (pageResult.EvaluateResult(out var returnValue))
return returnValue;
return IgnoreResult.Value;
}
finally
{
scope.PageResult.StackDepth--;
}
};
return Tuple.Create(strName, invoker);
});
scope.PageResult.Args[invokerCtx.Item1] = invokerCtx.Item2;
return TypeConstants.EmptyTask;
}
}
}
You can’t perform that action at this time.