jsonpiler 0.11.0

a Json syntax programming language for Windows
Documentation
use crate::prelude::*;
const ENTER: &str = "EnterCriticalSection";
const LEAVE: &str = "LeaveCriticalSection";
impl Jsonpiler {
  pub(crate) fn assign(
    &mut self,
    is_global_opt: Option<bool>,
    (name, val): KeyVal,
    scope: &mut Scope,
  ) -> ErrOR<bool> {
    let reassign = if let Some(is_g) = is_global_opt {
      self.check_defined(&name, name.pos, GlobalVar, scope)?;
      Err(is_g)
    } else {
      let var = self.get_var(&name, scope)?.val;
      if var.val.as_type() != val.val.as_type() {
        let val_type = val.map_ref(Json::as_type);
        return Err(type_err(fmt_var(&name.val, var.kind), vec![var.val.as_type()], val_type));
      }
      let Some(mem) = var.val.mem() else {
        return err!(name.pos, UndefinedVar(name.val.clone()));
      };
      Ok(mem)
    };
    let is_global = reassign.is_err_and(|is_g| is_g);
    let call_once = scope.loop_labels.is_empty() && scope.epilogue.is_none();
    let data_sect = is_global && call_once;
    let value = match &val.val {
      Bool(Lit(lit)) if data_sect => Bool(Var(self.global_b(*lit))),
      Int(Lit(int)) if data_sect => Int(Var(self.global_q(int.cast_unsigned()))),
      Float(Lit(lit)) if data_sect => Float(Var(self.global_q(lit.to_bits()))),
      Null(_) | Array(..) | Bool(_) | Float(_) | Int(_) | Object(_) | Str(_) => {
        if is_global {
          if self.flags.a64 {
            self.os_unfair_lock(scope, true)?;
          } else {
            self.critical_sect(scope, ENTER)?;
          }
        }
        let val_type = val.val.as_type();
        let mem_type = val_type.mem_type(val.pos)?;
        let size = mem_type.size()?;
        let mem = match reassign {
          Ok(mem) => {
            self.heap_free(mem, scope)?;
            mem
          }
          Err(is_g) => Memory(
            if is_g {
              let size_u32 = u32::try_from(size)?;
              Global(self.bss(size_u32, size_u32))
            } else {
              Local(Long, scope.alloc(size, size)?)
            },
            MemType { pass_by: Value, size: Small(mem_type.reg_size()) },
          ),
        };
        let value = val_type.to_json(val.pos, mem.0)?;
        if self.flags.a64 {
          scope.e_a(self.load_json_a(X0, &val, Some(scope.id))?)?;
          scope.e_a(store_a(mem, X1, X0)?)?;
        } else {
          scope.e_x(self.load_json_x(Rax, &val, Some(scope.id))?)?;
          scope.e_x(store_x(mem, Rcx, Rax)?)?;
        }
        self.drop_json(&val.val, false, scope)?;
        if is_global {
          if self.flags.a64 {
            self.os_unfair_lock(scope, false)?;
          } else {
            self.critical_sect(scope, LEAVE)?;
          }
        }
        value
      }
    };
    if let Err(is_g) = reassign {
      let target = if is_g { &mut self.globals } else { scope.innermost() };
      let kind = if is_g { GlobalVar } else { LocalVar };
      target.insert(name.val, name.pos.with(Variable::new(value, kind)));
    }
    Ok(reassign.is_ok())
  }
  fn critical_sect(&mut self, scope: &mut Scope, action: &'static str) -> ErrOR<()> {
    let critical_section = Global(self.get_critical_section()?);
    scope.e_x(vec![LeaRM(Rcx, critical_section), CallApi(self.api(KERNEL32, action))])
  }
  fn os_unfair_lock(&mut self, scope: &mut Scope, lock: bool) -> ErrOR<()> {
    let action = if lock { "_os_unfair_lock_lock" } else { "_os_unfair_lock_unlock" };
    let os_unfair_lock = Global(self.get_os_unfair_lock()?).ptr();
    scope.e_a(load_a(X0, os_unfair_lock)?)?;
    scope.p_a(BApi(self.api(SYS_B, action)))
  }
  fn reassign(&mut self, func: &mut Pos<BuiltIn>, scope: &mut Scope) -> ErrOR<Json> {
    let mut first = func.arg()?;
    if let Object(Lit(obj)) = &mut first.val
      && obj.len() == 1
      && (obj[0].0.val == "let" || obj[0].0.val == "global")
    {
      if let Some(builtin) = self.builtin.get_mut(&obj[0].0.val) {
        builtin.refs.push(obj[0].0.pos);
      }
      let is_global = obj[0].0.val == "global";
      let var = if let Array(_, Lit(args)) = &mut obj[0].1.val
        && args.len() == 1
      {
        take(&mut args[0])
      } else {
        take(&mut obj[0].1)
      }
      .into_ident("Variable name")?;
      let val = self.eval(func.arg()?, scope)?;
      self.assign(Some(is_global), (var, val), scope)?;
      return Ok(Null(Lit(())));
    }
    let name = first.into_ident("Variable name")?;
    let val = self.eval(func.arg()?, scope)?;
    if self.assign(None, (name.clone(), val), scope)? {
      Ok(Null(Lit(())))
    } else {
      err!(name.pos, UndefinedVar(name.val))
    }
  }
}
built_in! {self, _func, _scope, variable;
  {"global", SPECIAL, Exact(1),
    assign_global => {Ok(Null(Lit(()))) },
    assign_global_a => { Ok(Null(Lit(()))) }
  },
  {"let", SPECIAL, Exact(1),
    assign_local => { Ok(Null(Lit(()))) },
    assign_local_a => { Ok(Null(Lit(()))) }
  },
  {"=", SPECIAL, Exact(2),
    f_reassign => { self.reassign(_func, _scope) },
    f_reassign_a => { self.reassign(_func, _scope) }
  },
  {"$", COMMON, Exact(1),
    reference => { Ok(self.get_var(&arg!(_func, (Str(Lit(x))) => x), _scope)?.val.val.clone()) },
    reference_f => { Ok(self.get_var(&arg!(_func, (Str(Lit(x))) => x), _scope)?.val.val.clone()) }
  },
  {"scope", SP_SCOPE, Exact(1),
    scope => { Ok(self.eval(_func.arg()?, _scope)?.val) },
    scope_a => { Ok(self.eval(_func.arg()?, _scope)?.val) }
  }
}