function make_tvar_data,name,data,limits,dlimits
compile_opt hidden
if in_set('x',strlowcase(tag_names(data))) then begin
x = data.x
endif else begin
x = ''
endelse
if in_set('y',strlowcase(tag_names(data))) then begin
y = data.y
endif else begin
message,'Y component of tplot variable missing. Name: ' + name
endelse
if in_set('v',strlowcase(tag_names(data))) then begin
v = data.v
endif else begin
v = ''
endelse
if is_equal(limits,0) then begin
l = ''
endif else begin
l = limits
endelse
if is_equal(dlimits,0) then begin
dl = ''
endif else begin
dl = dlimits
endelse
return,{type:'tvar_data',name:name,times:x,data:y,yvalues:v,limits:l,dlimits:dl}
end
function make_var_data,name,data
compile_opt hidden
return,{type:'var_data',name:name,data:data}
end
function make_arg_list,arg,list
compile_opt hidden
if ~keyword_set(list) then begin
return,{type:'arg_list',data:arg,length:1,next:''}
endif
return,{type:'arg_list',data:arg,length:(list.length+1),next:list}
end
function make_data_type,tvar_type
compile_opt hidden
if ~is_tvar_data(tvar_type) || (is_equal(tvar_type.yvalues,'') && is_equal(tvar_type.times,'')) then begin
return,{y:tvar_type.data}
endif else if is_equal(tvar_type.yvalues,'') then begin
return,{x:tvar_type.times,y:tvar_type.data}
endif else if is_equal(tvar_type.times,'') then begin
return,{y:tvar_type.data,v:tvar_type.yvalues}
endif else begin
return,{x:tvar_type.times,y:tvar_type.data,v:tvar_type.yvalues}
endelse
end
function make_limits_type,tvar_type
compile_opt hidden
if ~is_tvar_data(tvar_type) || is_equal(tvar_type.limits,'') then begin
return,0
endif else begin
return,tvar_type.limits
endelse
end
function make_dlimits_type,tvar_type
compile_opt hidden
if ~is_tvar_data(tvar_type) || is_equal(tvar_type.dlimits,'') then begin
return,0
endif else begin
return,tvar_type.dlimits
endelse
end
function replace_data,var,data
compile_opt hidden
if is_var_data(var) then begin
return,make_var_data(var.name,data)
endif else begin
return,{type:var.type, $
name:var.name, $
times:var.times, $
data:data,$
yvalues:var.yvalues,$
limits:var.limits,$
dlimits:var.dlimits}
endelse
end
function dim_correct_data,data,xdim,opdim
compile_opt hidden
if opdim eq 1 && xdim gt 1 then begin
return,reform(data,[1,dimen(data)])
endif else begin
return,data
endelse
end
function reduce_times,var,dim
compile_opt hidden
if is_tvar_data(var) && ~is_equal(var.times,'') && $
(~keyword_set(dim) || dim.data eq 0 || dim.data eq 1) then begin
return,{type:var.type, $
name:var.name, $
times:ndimen(var.times)?median(var.times,/even):median([var.times],/even), $
data:var.data,$
yvalues:var.yvalues,$
limits:var.limits,$
dlimits:var.dlimits}
endif else begin
return,var
endelse
end
function reduce_yvalues,var,dim
compile_opt hidden
if is_tvar_data(var) && ~is_equal(var.yvalues,'') then begin
if ~keyword_set(dim) || dim.data eq 0 then begin
return,{type:var.type, $
name:var.name, $
times:var.times, $
data:var.data,$
yvalues:ndimen(var.yvalues)?median(var.yvalues,/even):median([var.yvalues],/even),$
limits:var.limits,$
dlimits:var.dlimits}
endif else if dim.data eq 1 then begin
if ndimen(var.yvalues) ge 2 then begin
return,{type:var.type, $
name:var.name, $
times:var.times, $
data:var.data,$
yvalues:dim_correct_data(median(var.yvalues,dim=1,/even),ndimen(var.yvalues),1),$
limits:var.limits,$
dlimits:var.dlimits}
endif
endif else if dim.data eq 2 then begin
if ndimen(var.yvalues) ge 2 then begin
return,{type:var.type, $
name:var.name, $
times:var.times, $
data:var.data,$
yvalues:median(var.yvalues,dim=2,/even),$
limits:var.limits,$
dlimits:var.dlimits}
endif else begin
return,{type:var.type, $
name:var.name, $
times:var.times, $
data:var.data,$
yvalues:ndimen(var.yvalues)?median(var.yvalues,/even):median([var.yvalues],/even),$
limits:var.limits,$
dlimits:var.dlimits}
endelse
endif
endif
return,var
end
function reduce_dlimits,var,label,dim
if ~keyword_set(dim) || dim.data ne 2 then return,var
var_out = var
dlimits = make_dlimits_type(var)
if keyword_set(dlimits) then begin
if in_set(strlowcase(tag_names(dlimits)),'dlimits') then begin
dl = dlimits.dlimits
endif else begin
dl = dlimits
endelse
if in_set(strlowcase(tag_names(dl)),'colors') && n_elements(dl.colors) gt 1 then begin
str_element,dl,'colors',0,/add
endif
if in_set(strlowcase(tag_names(dl)),'labels') && n_elements(dl.labels) gt 1 then begin
str_element,dl,'labels',label,/add
endif
if in_set(strlowcase(tag_names(dlimits)),'dlimits') then begin
str_element,dlimits,'dlimits',dl,/add
endif else begin
dlimits = dl
endelse
str_element,var_out,'dlimits',dlimits,/add
endif
limits = make_limits_type(var)
if keyword_set(limits) then begin
if in_set(strlowcase(tag_names(limits)),'colors') && n_elements(limits.colors) gt 1 then begin
str_element,limits,'colors',0,/add
endif
if in_set(strlowcase(tag_names(limits)),'labels') && n_elements(limits.labels) gt 1 then begin
str_element,limits,'labels',label,/add
endif
str_element,var_out,'limits',limits,/add
endif
return,var_out
end
function is_tvar_type,in
compile_opt idl2,hidden
mini_predicates
if is_string_type(in) then begin
return,1
endif else begin
return,0
endelse
end
function is_var_type,in
compile_opt idl2,hidden
mini_predicates
if is_identifier_type(in) then begin
return,1
endif else begin
return,0
endelse
end
pro store_var_data,name,value
compile_opt hidden
if is_tvar_type(name) then begin
overwrite_selection = ''
overwrite_count = (*!mini_globals.replay_struct).overwrite_count
gui_prompt_obj = (*!mini_globals.replay_struct).calc_prompt_obj
if (*!mini_globals.replay_struct).replay ne 1 then begin
previous_selection = (*!mini_globals.replay_struct).overwrite_selections[n_elements((*!mini_globals.replay_struct).overwrite_selections)-1]
endif else begin
whereyestoall = where((*!mini_globals.replay_struct).overwrite_selections eq 'yestoall', yestoallcount)
wherenotoall = where((*!mini_globals.replay_struct).overwrite_selections eq 'notoall', notoallcount)
if yestoallcount then if (*!mini_globals.replay_struct).overwrite_count ge whereyestoall[0] then overwrite_selection = 'yestoall'
if notoallcount then if (*!mini_globals.replay_struct).overwrite_count ge wherenotoall[0] then overwrite_selection = 'notoall'
previous_selection = ''
endelse
if previous_selection eq 'notoall' then overwrite_selection = 'notoall'
if previous_selection eq 'yestoall' then overwrite_selection = 'yestoall'
if obj_valid(!mini_globals.gui_data_obj) then begin
names = !mini_globals.gui_data_obj->getall()
wherenames = where(name.value eq names, wherecount)
if wherecount gt 0 then begin
if overwrite_selection ne 'yestoall' then begin
if overwrite_selection eq 'notoall' then return
overwrite_selection = ''
if (*!mini_globals.replay_struct).replay ne 0 then begin
if overwrite_count gt n_elements((*!mini_globals.replay_struct).overwrite_selections) then begin
hwin = (*!mini_globals.replay_struct).historywin
sbar = (*!mini_globals.replay_struct).statusbar
if obj_valid(hwin) then hwin->update,"ERROR:Discrepancy in themis document, may have lead to a document load error"
if obj_valid(sbar) then sbar->update,"ERROR:Discrepancy in themis document, may have lead to a document load error"
overwrite_selection = "yestoall"
endif else begin
overwrite_selection = ((*!mini_globals.replay_struct).overwrite_selections)[overwrite_count]
endelse
endif else begin
prompt = 'Do you want to overwrite '+name.value+' with the new data?'
if obj_valid(gui_prompt_obj) then begin
overwrite_selection = gui_prompt_obj->sendtoScreen(prompt, 'Overwrite Existing Data?', gui_id = (*!mini_globals.replay_struct).gui_id)
endif else begin
dprint,dlevel=0,'Error in store_var_data, no valid GUI prompt object'
endelse
newarray = array_concat_wrapper(overwrite_selection,(*!mini_globals.replay_struct).overwrite_selections)
str_element, *!mini_globals.replay_struct, 'overwrite_selections', newarray, /add_rep
endelse
(*!mini_globals.replay_struct).overwrite_count = (*!mini_globals.replay_struct).overwrite_count + 1
if overwrite_selection eq 'no' || overwrite_selection eq 'notoall' then begin
return
endif
endif
endif
data = make_data_type(value)
limits = make_limits_type(value)
tmp_limits = make_dlimits_type(value)
dlimits = tmp_limits.dlimits
obj = tmp_limits.object
obj->setProperty,name=name.value
store_data,name.value,data=data,limits=limits,dlimits=dlimits,error=e
if e then begin
message,'store_data error'
endif
if ~!mini_globals.gui_data_obj->addTvarObject(obj) then begin
message,'loaded_data error'
endif
endif else begin
limits = make_limits_type(value)
dlimits = make_dlimits_type(value)
str_element,limits,'ytitle',/delete
str_element,dlimits,'ytitle',/delete
str_element,limits,'ysubtitle',/delete
str_element,dlimits,'ysubtitle',/delete
str_element,limits,'yrange',/delete
str_element,dlimits,'yrange',/delete
str_element,limits,'ztitle',/delete
str_element,dlimits,'ztitle',/delete
str_element,limits,'zsubtitle',/delete
str_element,dlimits,'zsubtitle',/delete
str_element,limits,'zrange',/delete
str_element,dlimits,'zrange',/delete
store_data,name.value,data=make_data_type(value),limits=limits,dlimit=dlimits,error=e
if e then begin
message,'store_data error'
endif
endelse
endif else if is_var_type(name) then begin
(scope_varfetch(name.value,/enter,level=!mini_globals.scope_level)) = value.data
endif else begin
message,'Wrong type in store_var_data'
endelse
end
function is_error_code,in
compile_opt idl2,hidden
if is_equal(in,'') then begin
return,1
endif else begin
return,0
endelse
end
function is_shift_code,in
compile_opt idl2,hidden
if strlen(in) gt 1 && strmid(in,0,1) eq 's' then begin
return,1
endif else begin
return,0
endelse
end
function get_shift_num,in
compile_opt idl2,hidden
if strlen(in) lt 2 then begin
return,-1
endif else begin
return,long(strmid(in,1))
endelse
end
function is_reduce_code,in
compile_opt idl2,hidden
if strlen(in) gt 1 && strmid(in,0,1) eq 'r' then begin
return,1
endif else begin
return,0
endelse
end
function is_valid_bop_arg,arg1,arg2,arg3
compile_opt idl2,hidden
dim1 = dimen(arg1.data)
dim2 = dimen(arg3.data)
ndim1 = ndimen(arg1.data)
ndim2 = ndimen(arg3.data)
if product(dim1) eq 1 || product(dim2) eq 1 then return,1
if arg2.name eq '#' then begin
if ndim1 eq 1 && ndim2 eq 1 then return,1
if ndim1 eq 1 && ndim2 eq 2 && $
dim1[0] eq dim2[0] then return,1
if ((ndim1 eq 2 && ndim2 eq 1) || $
(ndim1 eq 2 && ndim2 eq 2)) && $
dim1[1] eq dim2[0] then return,1
endif else if arg2.name eq '##' then begin
if ndim1 eq 1 && ndim2 eq 1 then return,1
if ndim1 eq 2 && ndim2 eq 1 && $
dim1[0] eq dim2[0] then return,1
if ((ndim1 eq 1 && ndim2 eq 2) || $
(ndim1 eq 2 && ndim2 eq 2)) && $
dim1[0] eq dim2[1] then return,1
endif else begin
if array_equal(dim1,dim2) then return,1
endelse
return,0
end
function get_reduce_num,in
compile_opt idl2,hidden
if strlen(in) lt 2 then begin
return,-1
endif else begin
return,long(strmid(in,1))
endelse
end
function eval_token,token,previous,grammar
compile_opt idl2,hidden
mini_predicates
mini_routines
if is_function_type(token) then begin
tk = get_function(token)
if ~is_struct(tk) then begin
return, {type:'error',name:'function lookup error',value:token.name,position:n}
endif else begin
tk.name = 'func'
ev = tk
endelse
endif else if is_var_type(token) then begin
ev = {type:token.type,name:'var',value:token.name,index:0}
endif else if is_tvar_type(token) then begin
ev = {type:token.type,name:'tvar',value:strmid(token.name,1,strlen(token.name)-2),index:0}
endif else if is_operator_type(token) then begin
ev = token
if token.name eq '-' then begin
if is_unary_minus(token,previous) then begin
ev.name = 'u-'
endif else begin
ev.name = 'b-'
endelse
ev.value = token.name
endif else if token.name eq '+' then begin
if is_unary_plus(token,previous) then begin
ev.name = 'u+'
endif else begin
ev.name = 'b+'
endelse
ev.value = token.name
endif else if token.name eq '/' then begin
if is_keyword_slash(token,previous) then begin
ev.name = 'k/'
endif else begin
ev.name = 'b/'
endelse
ev.value = ev.name
endif
endif else if is_assignment_type(token) then begin
ev = token
if strlen(token.value) gt 1 then begin
ev.value = strmid(token.value,0,1)
endif
if ev.value eq '-' then begin
ev.value = 'b-'
endif else if ev.value eq '+' then begin
ev.value = 'b+'
endif
endif else if is_numerical_type(token) then begin
if strpos(token.name,'u') ne -1 then begin
unsigned = 1
endif else begin
unsigned = 0
endelse
if strpos(token.name,'b') ne -1 then begin
ev = {type:token.type,name:'number',value:byte(token.name),index:0}
endif else if strpos(token.name,'s') ne -1 then begin
if unsigned then begin
ev = {type:token.type,name:'number',value:uint(token.name),index:0}
endif else begin
ev = {type:token.type,name:'number',value:fix(token.name),index:0}
endelse
endif else if strpos(token.name,'d') ne -1 then begin
ev = {type:token.type,name:'number',value:double(token.name),index:0}
endif else if strpos(token.name,'e') ne -1 || $
strpos(token.name,'.') ne -1 then begin
ev = {type:token.type,name:'number',value:float(token.name),index:0}
endif else if strpos(token.name,'ll') ne -1 then begin
if unsigned then begin
ev = {type:token.type,name:'number',value:ulong64(token.name),index:0}
endif else begin
ev = {type:token.type,name:'number',value:long64(token.name),index:0}
endelse
endif else if strpos(token.name,'l') ne -1 then begin
if unsigned then begin
ev = {type:token.type,name:'number',value:ulong(token.name),index:0}
endif else begin
ev = {type:token.type,name:'number',value:long(token.name),index:0}
endelse
endif else begin
ev = {type:token.type,name:'number',value:float(token.name),index:0}
endelse
endif else begin
ev = {type:token.type,name:token.name,value:token.name,index:0}
endelse
idx = where(ev.name eq grammar.terminals)
if idx[0] eq -1 then begin
message,'token should always evaluate to a terminal in language'
endif
ev.index = idx
return,ev
end
pro validate_mini_func_args,required_args,optional_args,keyword_list,arg_list
compile_opt hidden,strictarr
arg_count = 0
keyword_count = lonarr(n_elements(keyword_list))
arg_iter = arg_list
while keyword_set(arg_iter) do begin
if ~is_keyword_type(arg_iter.data) then begin
arg_count++
endif else begin
if ~keyword_set(keyword_list) then message,'Illegal keyword: ' + arg_iter.data.value
keyword_matches = stregex(keyword_list,'^'+arg_iter.data.value,/boolean,/fold_case)
idx = where(keyword_matches ne 0,c)
if c eq 0 then message,'Illegal keyword: ' + arg_iter.data.value
keyword_count += keyword_matches
idx = where(keyword_count gt 1,c)
if c gt 0 then message,'Ambiguous keyword: ' + arg_iter.data.value
endelse
arg_iter = arg_iter.next
endwhile
if arg_count lt required_args then message,'Missing required argument(s)'
if arg_count gt optional_args+required_args then message,'Too many arguments'
end
function is_mini_keyword_set,arg_list,keyword
compile_opt hidden,strictarr
if ~keyword_set(arg_list) then return,0
if is_keyword_type(arg_list.data) && $
stregex(keyword,'^'+arg_list.data.value,/boolean,/fold_case) then return,1
if arg_list.length gt 1 then return,is_mini_keyword_set(arg_list.next,keyword)
return,0
end
function get_positional_arg,arg_list,n
compile_opt hidden,strictarr
if ~keyword_set(arg_list) then return,0
if is_keyword_type(arg_list.data) then begin
if arg_list.length eq 1 then begin
return, 0
endif else begin
return, get_positional_arg(arg_list.next,n)
endelse
endif
if n eq 0 then return, arg_list.data
if arg_list.length eq 1 then return,0
return, get_positional_arg(arg_list.next,n-1)
end
pro evaluator_routines
end