<commit_before>namespace BooJs.Lang.Async

import BooJs.Lang.Extensions

import System
import Boo.Lang.Compiler
import Boo.Lang.Compiler.Ast


[Transform( __value )]
def __value() as object:
    pass
[Transform( __value )]
def __valuelist() as (object):
    pass


macro await:
    # await foo()
    # await foo(), bar()  <==>  (foo(), bar())
    # await data = foo()
    # await data = foo(), bar()
    # await data, data2 = foo(), bar()

    # TODO: Support type definitions

    decls = ExpressionCollection()
    exprs = ExpressionCollection()
    list = decls
    for arg in await.Arguments:
        if be = arg as BinaryExpression:
            if be.Operator != BinaryOperatorType.Assign:
                raise 'Invalid operator, only simple assigns are allowed'
            decls.Add(be.Left)
            exprs.Add(be.Right)
            list = exprs
            continue

        list.Add(arg)

    if len(exprs) == 1:
        yield [| yield $(exprs[0]) |]
    else:
        yield [| yield $( ArrayLiteralExpression(Items: exprs) ) |]

    if len(decls) == 1:
        yield [| $(decls[0]) = BooJs.Lang.Async.__value() |]
    elif len(decls) > 1:
        unpack = UnpackStatement()
        for decl as ReferenceExpression in decls:
            unpack.Declarations.Add(Declaration(Name: decl.Name))
        unpack.Expression = [| BooJs.Lang.Async.__valuelist() |]
        yield unpack




[AttributeUsage(AttributeTargets.Method)]
class AsyncAttribute(AbstractAstAttribute):

    def Apply(node as Node):
        method = node as Method
        method.Body = [|
            return async(): $(method.Body)
        |].ToBlock()



interface IPromise:
    def _then(okHandler as callable, errorHandler as callable, progressHandler as callable) as IPromise


class Promise(IPromise):

    def constructor(defer as Deferred):
        pass

    def done(fn as callable(object)) as Promise:
        pass

    def fail(fn as callable(object)) as Promise:
        pass

    def always(fn as callable(object)) as Promise:
        pass
<commit_msg>Issue a warning if the await macro is used without async<commit_after>namespace BooJs.Lang.Async

import System
import Boo.Lang.Environments
import Boo.Lang.Compiler
import Boo.Lang.Compiler.Ast

import BooJs.Lang.Extensions


[Transform( __value )]
def __value() as object:
    pass
[Transform( __value )]
def __valuelist() as (object):
    pass


macro await:
    # await foo()
    # await foo(), bar()  <==>  (foo(), bar())
    # await data = foo()
    # await data = foo(), bar()
    # await data, data2 = foo(), bar()

    # TODO: Support type definitions

    # Check if the macro is used with async
    has_async = false
    parent = await.ParentNode
    while parent:
        if mie = parent as MethodInvocationExpression:
            target = mie.Target as ReferenceExpression
            if target and target.Name == 'async':
                has_async = true
                break

        parent = parent.ParentNode

    if not has_async:
        warning = CompilerWarningFactory.CustomWarning(await, 'await macro is being used in a method without the async attribute')
        my(CompilerContext).Warnings.Add(warning)

    decls = ExpressionCollection()
    exprs = ExpressionCollection()
    list = decls
    for arg in await.Arguments:
        if be = arg as BinaryExpression:
            if be.Operator != BinaryOperatorType.Assign:
                raise 'Invalid operator, only simple assigns are allowed'
            decls.Add(be.Left)
            exprs.Add(be.Right)
            list = exprs
            continue

        list.Add(arg)

    # No expressions mean we are not handling an assignment operation
    if len(exprs) == 0:
        exprs, decls = decls, exprs

    if len(exprs) == 1:
        yield [| yield $(exprs[0]) |]
    else:
        yield [| yield $( ArrayLiteralExpression(Items: exprs) ) |]

    if len(decls) == 1:
        yield [| $(decls[0]) = BooJs.Lang.Async.__value() |]
    elif len(decls) > 1:
        unpack = UnpackStatement()
        for decl as ReferenceExpression in decls:
            unpack.Declarations.Add(Declaration(Name: decl.Name))
        unpack.Expression = [| BooJs.Lang.Async.__valuelist() |]
        yield unpack




[AttributeUsage(AttributeTargets.Method)]
class AsyncAttribute(AbstractAstAttribute):

    def Apply(node as Node):
        method = node as Method
        method.Body = [|
            return async(): $(method.Body)
        |].ToBlock()



interface IPromise:
    def _then(okHandler as callable, errorHandler as callable, progressHandler as callable) as IPromise


internal class Promise(IPromise):

    def constructor(defer as Deferred):
        pass

    def done(fn as callable(object)) as Promise:
        pass

    def fail(fn as callable(object)) as Promise:
        pass

    def always(fn as callable(object)) as Promise:
        pass

{'fraction_non_alphanumeric': 0.10213727907932593, 'fraction_numerical': 0.0026715988491574187, 'mean_word_length': 2.47891350964975, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6404347', 'n_tokens_mistral': 1447, 'n_tokens_neox': 1390, 'n_words': 427}