Download
106 lines 4.2 KiBMoonScriptModified 2022-10-03 raw
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
-- Custom implementations of list methods
import FnType, OptionalType, NilType, Bool, String, Int, ListType from require 'types'
import log, viz, node_assert, node_error, each_tag, context_err from require 'util'

types = {
    lowercase: => FnType({@},@,{"str"})
    uppercase: => FnType({@},@,{"str"})
    capitalized: => FnType({@},@,{"str"})
    titlecased: => FnType({@},@,{"str"})
    repeated: => FnType({@,Int},@,{"str","times"})
    starts_with: => FnType({@,@},Bool,{"str","prefix"})
    ends_with: => FnType({@,@},Bool,{"str","suffix"})
    strip: => FnType({@,OptionalType(@),OptionalType(Bool),OptionalType(Bool)},@,{"str","chars","left","right"})
    split: => FnType({@,@,OptionalType(Int)}, ListType(@), {"str","on","max_splits"})
    lines: => FnType({@}, ListType(@), {"str"})
    replacing: => FnType({@,@,@,OptionalType(Int)}, @, {"str","pattern","replacement","limit"})
    matches: => FnType({@,@}, Bool, {"str","pattern"})
    -- find: => FnType({@,@,OptionalType(Int)}, OptionalType(Int), {"str","target","start"})
    -- - matches() -> Bool
}

call_c_func = (code, cfunc)=>
    str = @fn and @fn.value or @[1]
    str_reg = code\add_value str
    result = code\fresh_locals "result"
    code\add "#{result} =l call $#{cfunc}(l #{str_reg})\n"
    return result

methods = {
    lowercase: (code)=> call_c_func(@, code, "bl_string_lower")
    uppercase: (code)=> call_c_func(@, code, "bl_string_upper")
    capitalized: (code)=> call_c_func(@, code, "bl_string_capitalized")
    titlecased: (code)=> call_c_func(@, code, "bl_string_titlecased")

    repeated: (code)=>
        args, err = types.repeated(@__type)\parse_args({@fn.value, table.unpack(@)})
        node_assert args, @, err
        str_reg, times_reg = code\add_values args.str, args.times
        result = code\fresh_locals "result"
        code\add "#{result} =l call $bl_string_repeat(l #{str_reg}, l #{times_reg})\n"
        return result

    starts_with: (code)=>
        args, err = types.starts_with(@__type)\parse_args({@fn.value, table.unpack(@)})
        node_assert args, @, err
        str_reg, prefix_reg = code\add_values args.str, args.prefix
        result = code\fresh_locals "result"
        code\add "#{result} =w call $bl_string_starts_with(l #{str_reg}, l #{prefix_reg})\n"
        return result
        
    ends_with: (code)=>
        args, err = types.ends_with(@__type)\parse_args({@fn.value, table.unpack(@)})
        node_assert args, @, err
        str_reg, prefix_reg = code\add_values args.str, args.suffix
        result = code\fresh_locals "result"
        code\add "#{result} =w call $bl_string_ends_with(l #{str_reg}, l #{prefix_reg})\n"
        return result

    strip: (code)=>
        args, err = types.strip(@__type)\parse_args({@fn.value, table.unpack(@)})
        node_assert args, @, err
        str_reg = code\add_value args.str
        chars_reg = if args.chars
            code\add_value args.chars
        else
            "#{String.nil_value}"

        left_reg = if args.left
            code\add_value args.left
        else
            "#{Bool.nil_value}"

        right_reg = if args.right
            code\add_value args.right
        else
            "#{Bool.nil_value}"

        result = code\fresh_locals "result"
        code\add "#{result} =l call $bl_string_strip(l #{str_reg}, l #{chars_reg}, w #{left_reg}, w #{right_reg})\n"
        return result

    replacing: (code)=>
        args, err = types.replacing(@__type)\parse_args({@fn.value, table.unpack(@)})
        node_assert args, @, err

        str_reg, pat_reg, replacement_reg = code\add_values args.str, args.pattern, args.replacement
        limit_reg = if args.limit
            code\add_value args.limit
        else
            "#{Int.nil_value}"

        result = code\fresh_locals "result"
        code\add "#{result} =l call $bl_string_replace(l #{str_reg}, l #{pat_reg}, l #{replacement_reg}, l #{limit_reg})\n"
        return result

    matches: (code)=>
        args, err = types.matches(@__type)\parse_args({@fn.value, table.unpack(@)})
        node_assert args, @, err

        str_reg, pat_reg = code\add_values args.str, args.pattern
        result = code\fresh_locals "result"
        code\add "#{result} =w call $bl_string_matches(l #{str_reg}, l #{pat_reg})\n"
        return result
}

return {:methods, :types}