<commit_before>﻿module IronJS.Compiler.Core

open IronJS
open IronJS.Aliases
open IronJS.Tools
open IronJS.Tools.Dlr
open IronJS.Compiler

#nowarn "25"

let private buildVarsMap (scope:Ast.FuncScope) =

  let (|Parameter|Local|) (l:Ast.LocalVar) = 
    if Ast.Local.isParameter l then Parameter else Local

  let (|NeedProxy|Not|) (l:Ast.LocalVar) =
    if Ast.Local.needsProxy l then NeedProxy else Not

  let createVar (l:Ast.LocalVar) =
    let clrTyp = Utils.Type.jsToClr l.UsedAs
    if Ast.Local.isClosedOver l 
      then Expr.param l.Name (Type.strongBoxType.MakeGenericType([|clrTyp|]))
      else Expr.param l.Name clrTyp

  let createProxy (l:Ast.LocalVar) =
    Expr.param (sprintf "%s_proxy" l.Name) scope.ArgTypes.[l.Index]

  scope.LocalVars
    |> Map.map(fun _ l -> 
                match l with
                | Parameter -> 
                  match l with
                  | NeedProxy -> Proxied(createVar l, createProxy l)
                  | Not -> Variable(createVar l, P)
                | Local -> 
                  Variable(createVar l, L)
              )

let private isLocal (_, v:Var) =
  match v with
  | Variable(_, L) -> true
  | Proxied(_, _) -> true
  | _ -> false

let private isParameter (_, v:Var) =
  match v with
  | Variable(_, P) -> true
  | Proxied(_, _) -> true
  | _ -> false

let private toParm (_, v:Var) =
  match v with
  | Variable(p, P) -> p
  | Proxied(_, p)  -> p
  | _ -> failwith "Que?"

let private toLocal (_, v:Var) =
  match v with
  | Variable(p, L) -> p
  | Proxied(l, _)  -> l
  | _ -> failwith "Que?"

let private isProxied (_, v:Var) =
  match v with
  | Proxied(_, _) -> true
  | _ -> false

(*Compiles a Ast.Node tree into a DLR Expression-tree*)
let compileAst (env:Runtime.Environment) (delegateType:ClrType) (closureType:ClrType) (scope:Ast.FuncScope) (ast:Ast.Node) =

  let ctx = {
    Context.New with
      Closure = Dlr.Expr.param "~closure" closureType
      Scope = scope
      Builder = Compiler.ExprGen.builder
      TemporaryTypes = new SafeDict<string, ClrType>()
      Environment = env
      Locals = buildVarsMap scope
  }

  let initGlobals = 
    let field = Expr.field ctx.EnvironmentExpr "Globals"
    Expr.assign ctx.Globals field

  let initClosure = 
    let field = Expr.field ctx.Function "Closure"
    Expr.assign ctx.Closure (Expr.cast closureType field)

  (*Initialize proxied parameters*)
  let initProxied = 
    ctx.Locals
      |> Map.toSeq
      |> Seq.filter isProxied
      |> Seq.map (fun (_, Proxied(var, proxy)) ->
           if Type.isStrongBox var.Type 
             then Expr.assign var (Expr.newArgs var.Type [proxy])
             else Expr.assign var (Expr.cast var.Type proxy)
         )
      #if DEBUG
      |> Seq.toArray
      #endif

  (*Initialize closed over variables and parameters*)
  let initClosedOver = 
    ctx.Scope.LocalVars
      |> Map.toSeq
      |> Seq.map (fun pair -> snd pair)
      |> Seq.filter (fun l -> Ast.Local.isClosedOver l)
      |> Seq.filter (fun l -> not (Ast.Local.needsProxy l))
      |> Seq.map (fun l -> 
           let expr = ctx.LocalExpr l.Name
           Expr.assign expr (Expr.new' expr.Type) 
         )
      #if DEBUG
      |> Seq.toArray
      #endif

  (*Initialize variables that need to be set as undefined*)
  let initUndefined =
    ctx.Scope.LocalVars
      |> Map.toSeq
      |> Seq.map (fun pair -> snd pair)
      |> Seq.filter (fun l -> Ast.Local.initToUndefined l)
      |> Seq.map (fun l -> 
           let expr = ctx.LocalExpr l.Name
           Utils.Assign.value expr Runtime.Undefined.InstanceExpr
         )
      #if DEBUG
      |> Seq.toArray
      #endif

  (*Assemble the function body expression*)
  let body = 
    (ctx.Builder2 ast :: Expr.labelExprT<Runtime.Box> ctx.Return :: [])
      |> List.toSeq
      |> Seq.append initUndefined
      |> Seq.append initClosedOver
      |> Seq.append initProxied
      |> Seq.append (initGlobals :: initClosure :: [])
      #if DEBUG
      |> Seq.toArray
      |> fun x -> Expr.block x
      #endif
    
  (*Resolve all locals that are parameters*)<commit_msg>Normalized variable names for Ast.LocalVar<commit_after>﻿module IronJS.Compiler.Core

open IronJS
open IronJS.Aliases
open IronJS.Tools
open IronJS.Tools.Dlr
open IronJS.Compiler

#nowarn "25"

let private buildVarsMap (scope:Ast.FuncScope) =

  let (|Parameter|Local|) (lv:Ast.LocalVar) = 
    if Ast.Local.isParameter lv then Parameter else Local

  let (|NeedProxy|Not|) (lv:Ast.LocalVar) =
    if Ast.Local.needsProxy lv then NeedProxy else Not

  let createVar (l:Ast.LocalVar) =
    let clrTyp = Utils.Type.jsToClr l.UsedAs
    if Ast.Local.isClosedOver l 
      then Expr.param l.Name (Type.strongBoxType.MakeGenericType([|clrTyp|]))
      else Expr.param l.Name clrTyp

  let createProxy (l:Ast.LocalVar) =
    Expr.param (sprintf "%s_proxy" l.Name) scope.ArgTypes.[l.Index]

  scope.LocalVars
    |> Map.map(fun _ lv -> 
                match lv with
                | Parameter -> 
                  match lv with
                  | NeedProxy -> Proxied(createVar lv, createProxy lv)
                  | Not -> Variable(createVar lv, P)
                | Local -> 
                  Variable(createVar lv, L)
              )

let private isLocal (_, v:Var) =
  match v with
  | Variable(_, L) -> true
  | Proxied(_, _) -> true
  | _ -> false

let private isParameter (_, v:Var) =
  match v with
  | Variable(_, P) -> true
  | Proxied(_, _) -> true
  | _ -> false

let private toParm (_, v:Var) =
  match v with
  | Variable(p, P) -> p
  | Proxied(_, p)  -> p
  | _ -> failwith "Que?"

let private toLocal (_, v:Var) =
  match v with
  | Variable(p, L) -> p
  | Proxied(l, _)  -> l
  | _ -> failwith "Que?"

let private isProxied (_, v:Var) =
  match v with
  | Proxied(_, _) -> true
  | _ -> false

(*Compiles a Ast.Node tree into a DLR Expression-tree*)
let compileAst (env:Runtime.Environment) (delegateType:ClrType) (closureType:ClrType) (scope:Ast.FuncScope) (ast:Ast.Node) =

  let ctx = {
    Context.New with
      Closure = Dlr.Expr.param "~closure" closureType
      Scope = scope
      Builder = Compiler.ExprGen.builder
      TemporaryTypes = new SafeDict<string, ClrType>()
      Environment = env
      Locals = buildVarsMap scope
  }

  let initGlobals = 
    let field = Expr.field ctx.EnvironmentExpr "Globals"
    Expr.assign ctx.Globals field

  let initClosure = 
    let field = Expr.field ctx.Function "Closure"
    Expr.assign ctx.Closure (Expr.cast closureType field)

  (*Initialize proxied parameters*)
  let initProxied = 
    ctx.Locals
      |> Map.toSeq
      |> Seq.filter isProxied
      |> Seq.map (fun (_, Proxied(var, proxy)) ->
           if Type.isStrongBox var.Type 
             then Expr.assign var (Expr.newArgs var.Type [proxy])
             else Expr.assign var (Expr.cast var.Type proxy)
         )
      #if DEBUG
      |> Seq.toArray
      #endif

  (*Initialize closed over variables and parameters*)
  let initClosedOver = 
    ctx.Scope.LocalVars
      |> Map.toSeq
      |> Seq.map (fun pair -> snd pair)
      |> Seq.filter (fun lv -> Ast.Local.isClosedOver lv)
      |> Seq.filter (fun lv -> not (Ast.Local.needsProxy lv))
      |> Seq.map (fun lv -> 
           let expr = ctx.LocalExpr lv.Name
           Expr.assign expr (Expr.new' expr.Type) 
         )
      #if DEBUG
      |> Seq.toArray
      #endif

  (*Initialize variables that need to be set as undefined*)
  let initUndefined =
    ctx.Scope.LocalVars
      |> Map.toSeq
      |> Seq.map (fun pair -> snd pair)
      |> Seq.filter (fun lv -> Ast.Local.initToUndefined lv)
      |> Seq.map (fun lv -> 
           let expr = ctx.LocalExpr lv.Name
           Utils.Assign.value expr Runtime.Undefined.InstanceExpr
         )
      #if DEBUG
      |> Seq.toArray
      #endif

  (*Assemble the function body expression*)
  let body = 
    (ctx.Builder2 ast :: Expr.labelExprT<Runtime.Box> ctx.Return :: [])
      |> List.toSeq
      |> Seq.append initUndefined
      |> Seq.append initClosedOver
      |> Seq.append initProxied
      |> Seq.append (initGlobals :: initClosure :: [])
      #if DEBUG
      |> Seq.toArray
      |> fun x -> Expr.block x
      #endif
    
  (*Resolve all locals that are parameters*)
{'fraction_non_alphanumeric': 0.11766853248965685, 'fraction_numerical': 0.0007301046483329277, 'mean_word_length': 2.2460505529225907, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 109, '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': '6236228', 'n_tokens_mistral': 2882, 'n_tokens_neox': 2717, 'n_words': 713}