aboutsummaryrefslogtreecommitdiff
path: root/src/gen/gen_eval.lua
blob: 1bcb939c72f4e59ef1a0483ec0b692adf6e90c0f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
---@diagnostic disable: no-unknown
local mpack = vim.mpack

local funcsfname = arg[1]
local metadata_file = arg[2]
local funcs_file = arg[3]
local eval_file = arg[4]

--Will generate funcs.generated.h with definition of functions static const array.

local hashy = require 'gen.hashy'

local hashpipe = assert(io.open(funcsfname, 'wb'))

hashpipe:write([[
#include "nvim/arglist.h"
#include "nvim/channel.h"
#include "nvim/cmdexpand.h"
#include "nvim/cmdhist.h"
#include "nvim/diff.h"
#include "nvim/digraph.h"
#include "nvim/eval.h"
#include "nvim/eval/buffer.h"
#include "nvim/eval/deprecated.h"
#include "nvim/eval/fs.h"
#include "nvim/eval/funcs.h"
#include "nvim/eval/list.h"
#include "nvim/eval/typval.h"
#include "nvim/eval/vars.h"
#include "nvim/eval/window.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_getln.h"
#include "nvim/fold.h"
#include "nvim/fuzzy.h"
#include "nvim/indent.h"
#include "nvim/indent_c.h"
#include "nvim/input.h"
#include "nvim/insexpand.h"
#include "nvim/mapping.h"
#include "nvim/match.h"
#include "nvim/mbyte.h"
#include "nvim/menu.h"
#include "nvim/mouse.h"
#include "nvim/move.h"
#include "nvim/quickfix.h"
#include "nvim/runtime.h"
#include "nvim/search.h"
#include "nvim/sign.h"
#include "nvim/state.h"
#include "nvim/strings.h"
#include "nvim/testing.h"
#include "nvim/undo.h"

]])

local funcs = loadfile(eval_file)().funcs
for name, func in pairs(funcs) do
  local n = (func.func_float and 1 or 0) + (func.func_lua and 1 or 0) + (func.func and 1 or 0)
  assert(n <= 1, name .. ': only one of func, func_float, func_lua can be set')

  if func.func_float then
    func.func = 'float_op_wrapper'
    func.data = '{ .func_float = &' .. func.func_float .. ' }'
  elseif func.func_lua then
    func.func = 'lua_wrapper'
    func.data = '{ .func_lua = "' .. func.func_lua .. '" }'
  end
end

local metadata = mpack.decode(io.open(metadata_file, 'rb'):read('*all'))
for _, fun in ipairs(metadata) do
  if fun.eval then
    local args
    if type(fun.opts_idx) == 'number' then
      args = { fun.opts_idx - 1, #fun.parameters }
    else
      args = #fun.parameters
    end
    funcs[fun.name] = {
      args = args,
      func = 'api_wrapper',
      data = '{ .func_api = &method_handlers[' .. fun.handler_id .. '] }',
    }
  end
end

local func_names = vim.tbl_filter(function(name)
  return name:match('__%d*$') == nil
end, vim.tbl_keys(funcs))

table.sort(func_names)

local funcsdata = assert(io.open(funcs_file, 'w'))
funcsdata:write(mpack.encode(func_names))
funcsdata:close()

local neworder, hashfun = hashy.hashy_hash('find_internal_func', func_names, function(idx)
  return 'functions[' .. idx .. '].name'
end)

hashpipe:write('static const EvalFuncDef functions[] = {\n')

for _, name in ipairs(neworder) do
  local def = funcs[name]
  local min_args = 0
  local max_args = 0 --- @type integer|string
  local def_args = def.args
  if type(def_args) == 'number' then
    min_args, max_args = def_args, def_args
  elseif type(def_args) == 'table' then
    min_args = def_args[1] or 0
    max_args = def_args[2] or 'MAX_FUNC_ARGS'
  end
  local base = def.base or 'BASE_NONE'
  local func = def.func or ('f_' .. name)
  local data = def.data or '{ .null = NULL }'
  local fast = def.fast and 'true' or 'false'
  hashpipe:write(
    ('  { "%s", %s, %s, %s, %s, &%s, %s },\n'):format(
      name,
      min_args,
      max_args,
      base,
      fast,
      func,
      data
    )
  )
end
hashpipe:write('  { NULL, 0, 0, BASE_NONE, false, NULL, { .null = NULL } },\n')
hashpipe:write('};\n\n')
hashpipe:write(hashfun)
hashpipe:close()